/*
 * Copyright 2008, Freescale Semiconductor, Inc
 * Andy Fleming
 *
 * Based vaguely on the Linux code
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <config.h>
#include <common.h>
#include <command.h>
#include <mmc.h>
#include <part.h>
#include <malloc.h>
#include <linux/list.h>
#include <div64.h>

#include "mmc_def.h"
#include <sys_config.h>
#include <asm/arch/clock.h>

DECLARE_GLOBAL_DATA_PTR;
/* Set block count limit because of 16 bit register limit on some hardware*/
#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
#endif

//static struct list_head mmc_devices;
//static int cur_dev_num = -1;
static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst);
static ulong mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src);

int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd);
static int mmc_decode_ext_csd(struct mmc *mmc,struct mmc_ext_csd *dec_ext_csd, u8 *ext_csd);
int mmc_do_switch(struct mmc *mmc, u8 set, u8 index, u8 value, u32 timeout);

LIST_HEAD(mmc_devices);

static const unsigned int tacc_exp[] = {
	1,	10,	100,	1000,	10000,	100000,	1000000, 10000000,
};

static const unsigned int tacc_mant[] = {
	0,	10,	12,	13,	15,	20,	25,	30,
	35,	40,	45,	50,	55,	60,	70,	80,
};

int __board_mmc_getcd(u8 *cd, struct mmc *mmc) {
	return -1;
}

int board_mmc_getcd(u8 *cd, struct mmc *mmc)__attribute__((weak,
	alias("__board_mmc_getcd")));

int mmc_update_phase(struct mmc *mmc)
{
	return mmc->update_phase(mmc);
}

int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
#ifdef CONFIG_MMC_TRACE
	int ret;
	int i;
	u8 *ptr;

	MMCDBG("CMD_SEND:%d\n", cmd->cmdidx);
	MMCDBG("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
	MMCDBG("\t\tFLAG\t\t\t %d\n", cmd->flags);
	ret = mmc->send_cmd(mmc, cmd, data);
	switch (cmd->resp_type) {
		case MMC_RSP_NONE:
			MMCDBG("\t\tMMC_RSP_NONE\n");
			break;
		case MMC_RSP_R1:
			MMCDBG("\t\tMMC_RSP_R1,5,6,7 \t 0x%08X \n",
				cmd->response[0]);
			break;
		case MMC_RSP_R1b:
			MMCDBG("\t\tMMC_RSP_R1b\t\t 0x%08X \n",
				cmd->response[0]);
			break;
		case MMC_RSP_R2:
			MMCDBG("\t\tMMC_RSP_R2\t\t 0x%08X \n",
				cmd->response[0]);
			MMCDBG("\t\t          \t\t 0x%08X \n",
				cmd->response[1]);
			MMCDBG("\t\t          \t\t 0x%08X \n",
				cmd->response[2]);
			MMCDBG("\t\t          \t\t 0x%08X \n",
				cmd->response[3]);
			MMCMSG("\n");
			MMCDBG("\t\t\t\t\tDUMPING DATA\n");
			for (i = 0; i < 4; i++) {
				int j;
				MMCMSG("\t\t\t\t\t%03d - ", i*4);
				ptr = (u8 *)(&cmd->response[i]);
				ptr += 3;
				for (j = 0; j < 4; j++)
					MMCMSG("%02X ", *ptr--);
				MMCMSG("\n");
			}
			break;
		case MMC_RSP_R3:
			MMCDBG("\t\tMMC_RSP_R3,4\t\t 0x%08X \n",
				cmd->response[0]);
			break;
		default:
			MMCDBG("\t\tERROR MMC rsp not supported\n");
			break;
	}
	return ret;
#else
	return mmc->send_cmd(mmc, cmd, data);
#endif
}

int mmc_send_status(struct mmc *mmc, int timeout)
{
	struct mmc_cmd cmd;
	int err;
#ifdef CONFIG_MMC_TRACE
	int status;
#endif

#if defined(CONFIG_ARCH_SUN9IW1P1)
	if(gd->securemode == SUNXI_SECURE_MODE_NO_SECUREOS)
		return 0;
#endif

	cmd.cmdidx = MMC_CMD_SEND_STATUS;
	cmd.resp_type = MMC_RSP_R1;
	if (!mmc_host_is_spi(mmc))
		cmd.cmdarg = mmc->rca << 16;
	cmd.flags = 0;

	do {
		err = mmc_send_cmd(mmc, &cmd, NULL);
		if (err){
			MMCINFO("Send status failed\n");
			return err;
		}
		else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA)
			break;

		udelay(1000);

		if (cmd.response[0] & MMC_STATUS_MASK) {
			MMCINFO("Status Error: 0x%08X\n", cmd.response[0]);
			return COMM_ERR;
		}
	} while (timeout--);

#ifdef CONFIG_MMC_TRACE
	status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9;
	status = status;//avoid warning
	MMCDBG("CURR STATE:%d\n", status);
#endif
	if (timeout < 0) {
		MMCINFO("Timeout waiting card ready\n");
		return TIMEOUT;
	}
	return 0;
}

int mmc_set_blocklen(struct mmc *mmc, int len)
{
	struct mmc_cmd cmd;

	/*ddr mode not send blocklenth*/
	if(mmc->io_mode == MMC_MODE_DDR_52MHz ){
		return 0;
	}
	cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = len;
	cmd.flags = 0;

	return mmc_send_cmd(mmc, &cmd, NULL);
}

int mmc_set_erase_start_addr(struct mmc *mmc, unsigned int address)
{
	struct mmc_cmd cmd;
	int err = 0;
	int timeout = 300; //ms

	cmd.cmdidx = MMC_CMD_ERASE_GROUP_START;
	cmd.resp_type = MMC_RSP_R1;
	cmd.flags = 0;

	if (mmc->high_capacity)
		cmd.cmdarg = address;
	else
		cmd.cmdarg = address * mmc->write_bl_len;

	err = mmc_send_cmd(mmc, &cmd, NULL);
	if (err) {
		MMCINFO("%s: send erase start addr failed\n", __FUNCTION__);
		goto ERR_RET;
	}

	err = mmc_send_status(mmc, timeout); //ms

ERR_RET:
	return err;
}

int mmc_set_erase_end_addr(struct mmc *mmc, unsigned int address)
{
	struct mmc_cmd cmd;
	int err = 0;
	int timeout = 300; //ms

	cmd.cmdidx = MMC_CMD_ERASE_GROUP_END;
	cmd.resp_type = MMC_RSP_R1;
	cmd.flags = 0;

	if (mmc->high_capacity)
		cmd.cmdarg = address;
	else
		cmd.cmdarg = address * mmc->write_bl_len;

	err = mmc_send_cmd(mmc, &cmd, NULL);
	if (err) {
		MMCINFO("%s: send erase end addr failed\n", __FUNCTION__);
		goto ERR_RET;
	}

	err = mmc_send_status(mmc, timeout); //ms

ERR_RET:
	return err;
}

int mmc_launch_erase(struct mmc *mmc, unsigned int erase_arg)
{
	struct mmc_cmd cmd;

	cmd.cmdidx = MMC_CMD_ERASE;
	cmd.resp_type = MMC_RSP_R1b;
	cmd.cmdarg = erase_arg;
	cmd.flags = 0;

	return mmc_send_cmd(mmc, &cmd, NULL);
}

unsigned int mmc_sd_erase_timeout(struct mmc *mmc, unsigned int erase_arg,
	unsigned int qty)
{
	return 0xffffff;
}

/* calculate erase timeout based on CSD and current card clock frequency */
unsigned int mmc_mmc_def_erase_timeout(struct mmc *mmc)
{
	unsigned int erase_timeout = 0;
	unsigned int r2w_factor = (mmc->csd[3]>>26)&0x7;      //28:26
	unsigned int tacc_clks = ((mmc->csd[0]>>8)&0xFF)*100; //111:104
	unsigned int e = (mmc->csd[3]>>16)&0x7;
	unsigned int m = (mmc->csd[3]>>19)&0xF;
	unsigned int tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
	unsigned int mult = 10 << r2w_factor;

	unsigned int timeout_clks = tacc_clks * mult;
	unsigned int timeout_us;


	/* Avoid overflow: e.g. tacc_ns=80000000 mult=1280 */
	if (tacc_ns < 1000000)
		timeout_us = (tacc_ns * mult) / 1000;
	else
		timeout_us = (tacc_ns / 1000) * mult;

	/*
	 * ios.clock is only a target.  The real clock rate might be
	 * less but not that much less, so fudge it by multiplying by 2.
	 */
	timeout_clks <<= 1;
	timeout_us += (timeout_clks * 1000) / (mmc->clock / 1000);

	erase_timeout = timeout_us / 1000;

	/*
	 * Theoretically, the calculation could underflow so round up
	 * to 1ms in that case.
	 */
	if (!erase_timeout)
		erase_timeout = 1;

	return erase_timeout;
}

unsigned int mmc_mmc_update_timeout(struct mmc *mmc)
{
	int ret = 0;
	char ext_csd[512];
	struct mmc_ext_csd mmc_ext_csd;

	MMCDBG("+++%s\n", __FUNCTION__);

	ret = mmc_send_ext_csd(mmc, ext_csd);
	if (ret) {
		MMCINFO("send ext_csd failed\n");
		goto ERR_RET;
	}

	ret = mmc_decode_ext_csd(mmc, &mmc_ext_csd, (unsigned char *)ext_csd);
	if (ret) {
		MMCINFO("decode ext_csd failed\n");
		goto ERR_RET;
	}

	if (mmc_ext_csd.rev >= 4)
	{
		if (mmc_ext_csd.erase_group_def && mmc_ext_csd.hc_erase_timeout)
			mmc->erase_timeout = mmc_ext_csd.hc_erase_timeout;
		else
			mmc->erase_timeout = mmc_mmc_def_erase_timeout(mmc);

		mmc->trim_discard_timeout = mmc_ext_csd.trim_timeout;
		mmc->secure_erase_timeout = mmc->erase_timeout * mmc_ext_csd.sec_erase_mult;
		mmc->secure_trim_timeout  = mmc->erase_timeout * mmc_ext_csd.sec_trim_mult;
	}
	else
	{
		if (mmc_ext_csd.rev == 3) {
			if (mmc_ext_csd.erase_group_def && mmc_ext_csd.hc_erase_timeout)
				mmc->erase_timeout = mmc_ext_csd.hc_erase_timeout;
			else
				mmc->erase_timeout = mmc_mmc_def_erase_timeout(mmc);
		} else {
			mmc->erase_timeout = mmc_mmc_def_erase_timeout(mmc);
		}

		mmc->trim_discard_timeout = 0x0;
		mmc->secure_erase_timeout = 0x0;
		mmc->secure_trim_timeout  = 0x0;
	}

ERR_RET:
	MMCDBG("---%s %d\n", __FUNCTION__, ret);
	return ret;
}

unsigned int mmc_mmc_erase_timeout(struct mmc *mmc, unsigned int arg,
	unsigned int qty)
{
	unsigned int erase_timeout = 0;

	if (arg == MMC_DISCARD_ARG || arg == MMC_TRIM_ARG) {
		if (!mmc->trim_discard_timeout) {
			MMCINFO("invalid trim_discard_timeout is %d\n", mmc->trim_discard_timeout);
			goto ERR_RET;
		}
		erase_timeout = mmc->trim_discard_timeout;
	} else if (arg == MMC_ERASE_ARG) {
		if (!mmc->erase_timeout) {
			MMCINFO("invalid erase_timeout is %d\n", mmc->erase_timeout);
			goto ERR_RET;
		}
		erase_timeout = mmc->erase_timeout;
	} else if (arg == MMC_SECURE_ERASE_ARG) {
		if (!mmc->secure_erase_timeout) {
			MMCINFO("invalid secure_erase_timeout is %d\n", mmc->secure_erase_timeout);
			goto ERR_RET;
		}
		erase_timeout = mmc->secure_erase_timeout;
	} else if (arg == MMC_SECURE_TRIM1_ARG || arg == MMC_SECURE_TRIM2_ARG) {
		if (!mmc->secure_trim_timeout) {
			MMCINFO("invalid secure_trim_timeout is %d\n", mmc->secure_trim_timeout);
			goto ERR_RET;
		}
		erase_timeout = mmc->secure_trim_timeout;
	} else {
		MMCINFO("Unknown erase argument 0x%x\n", arg);
		goto ERR_RET;
	}

	erase_timeout *= qty;

	return erase_timeout;

ERR_RET:
	return 0;
}

unsigned int mmc_erase_timeout(struct mmc *mmc, unsigned int erase_arg,
	unsigned int qty)
{
	if (IS_SD(mmc))
		return mmc_sd_erase_timeout(mmc, erase_arg, qty);
	else {
		return mmc_mmc_erase_timeout(mmc, erase_arg, qty);
	}
}

int mmc_do_erase(struct mmc *mmc, unsigned int from,
	unsigned int to, unsigned int erase_arg)
{
	int err = 0;
	unsigned int timeout = 0;
	unsigned int qty = 0;

	MMCDBG("+++%s\n", __FUNCTION__);

	mmc_mmc_update_timeout(mmc);

	err = mmc_set_erase_start_addr(mmc, from);
	if (err) {
		MMCINFO("set erase start addr failed\n");
		goto ERR_RET;
	}

	err = mmc_set_erase_end_addr(mmc, to);
	if (err) {
		MMCINFO("set erase end addr failed\n");
		goto ERR_RET;
	}

	err = mmc_launch_erase(mmc, erase_arg);
	if (err) {
		MMCINFO("launch erase failed\n");
		goto ERR_RET;
	}

	if (IS_SD(mmc)) {
		qty = to - from + 1;
	} else {
		qty = (to - from)/mmc->erase_grp_size + 1;
	}
	timeout = mmc_erase_timeout(mmc, erase_arg, qty);
	if (!timeout) {
		MMCINFO("calculate timeout failed\n");
		err = -1;
		goto ERR_RET;
	}

	err = mmc_send_status(mmc, timeout); //ms

ERR_RET:

	MMCDBG("---%s %d\n", __FUNCTION__, err);
	return err;
}

int mmc_erase_group_aligned(struct mmc *mmc, unsigned int from,
	unsigned int nr)
{
	if (!mmc->erase_grp_size)
		return 0;
	if (from % mmc->erase_grp_size || nr % mmc->erase_grp_size)
		return 0;
	return 1;
}

void mmc_align_erase_group(struct mmc *mmc, unsigned int from,
	unsigned int nr, unsigned int *align_from, unsigned int *align_nr)
{
	unsigned int rem, start, cnt;

	MMCDBG("---start erase addr adjust... \n");
	MMCDBG("--1-- from: %d, nr: %d, erase_group: %d\n", from, nr, mmc->erase_grp_size);
	start = from;
	cnt = nr;

	rem = start % mmc->erase_grp_size;
	if (rem) {
		rem = mmc->erase_grp_size - rem;
		start += rem;
		if (cnt > rem)
			cnt -= rem;
		else {
			MMCINFO("after adjust start addr, no more space need to erase!!\n");
			goto RET;
		}
	}
	rem = cnt % mmc->erase_grp_size;
	if (rem)
		cnt -= rem;

	if (cnt == 0) {
		MMCINFO("after adjust nr, no more space need to erase!!\n");
	}

RET:
	MMCDBG("--2-- from: %d, nr: %d, erase_group: %d\n", start, cnt, mmc->erase_grp_size);
	*align_from = start;
	*align_nr = cnt;
	return ;
}

int mmc_erase(struct mmc *mmc, unsigned int from,
	unsigned int nr, unsigned int erase_arg)
{
	int ret;

	MMCDBG("+++%s\n", __FUNCTION__);

	if (nr == 0) {
		ret = 0;
		MMCINFO("No space need to be erased !\n");
		goto ERR_RET;
	}

	if (!IS_SD(mmc))
	{
		if ((erase_arg != MMC_ERASE_ARG)
			&& (erase_arg != MMC_SECURE_ERASE_ARG)
			&& (erase_arg != MMC_TRIM_ARG)
			&& (erase_arg != MMC_DISCARD_ARG)
 			&& (erase_arg != MMC_SECURE_TRIM1_ARG)) {
			ret = -1;
			MMCINFO("Unknown erase type!\n");
			goto ERR_RET;
		}

		if ((erase_arg == MMC_ERASE_ARG)
			||(erase_arg == MMC_SECURE_ERASE_ARG)) {
			ret = mmc_erase_group_aligned(mmc, from, nr);
			if (!ret) {
				ret = -1;
				MMCINFO("Erase addr is not erase group alignment!\n");
				goto ERR_RET;
			}
		}

		MMCINFO("erase from: %d, to: %d, cnt: %d, erase_group: %d\n",
			from, from+nr-1, nr, mmc->erase_grp_size);
		ret = mmc_do_erase(mmc, from, from+nr-1, erase_arg);
		if (ret) {
			ret = -1;
			MMCINFO("Do erase failed!\n");
			goto ERR_RET;
		}

		if (erase_arg == MMC_SECURE_TRIM1_ARG)
		{
			ret = mmc_do_erase(mmc, from, from+nr-1, MMC_SECURE_TRIM2_ARG);
			if (ret) {
				ret = -1;
				MMCINFO("Do secure trim step 2 failed!\n");
				goto ERR_RET;
			}
		}
	}
	else
	{
		MMCINFO("Don't support to erase SD card\n");
		ret = -1;
	}

ERR_RET:

	MMCDBG("--%s  ret%d\n", __FUNCTION__, ret);
	return ret;
}

#define MMC_SANITIZE_REQ_TIMEOUT 240000
int mmc_do_sanitize(struct mmc *mmc)
{
	int ret;

	MMCINFO("%s: start emmc sanitize...\n", __FUNCTION__);
	ret = mmc_do_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
					EXT_CSD_SANITIZE_START, 1,
					MMC_SANITIZE_REQ_TIMEOUT);
	MMCINFO("%s end emmc sanitzie, ret %d\n", __FUNCTION__, ret);
	return ret;
}

void mmc_add_skip_space(unsigned int *skip_space, int index,
	unsigned int from, unsigned int nr)
{
	MMCDBG("%s: %d from %d  nr %d\n", __FUNCTION__, index, from, nr);
	skip_space[0] |= 0x1<<index;
	skip_space[index*2 + 1] = from;
	skip_space[index*2 + 2] = nr;
}

int mmc_insecure_secure_erase(struct mmc *mmc, unsigned int from,
	unsigned int nr, unsigned int *skip_space, int secure)
{
	int ret = 0;
	unsigned int align_from = from, align_nr = nr;
	int skip;
	unsigned int last_skip_len;
	unsigned arg;

	skip = 0;
	last_skip_len = 0;
	skip_space[0] = 0x0;

	MMCDBG("%d %s: start erase, seucre %d...\n", __LINE__, __FUNCTION__, secure);
	ret = mmc_erase_group_aligned(mmc, from, nr);
	if (!ret) {
		mmc_align_erase_group(mmc, from, nr, &align_from, &align_nr);
	}

	if (align_nr == 0)
	{
		MMCINFO("after align erase group, no space need to erase, erase failed\n");
		mmc_add_skip_space(skip_space, skip, from, nr);
		ret = -1;
	}
	else
	{
		if (secure)
			arg = MMC_SECURE_ERASE_ARG;
		else
			arg = MMC_ERASE_ARG;

		ret = mmc_erase(mmc, align_from, align_nr, arg);
		if (ret) {
			MMCINFO("erase failed, range %d - %d \n",
				align_from, (align_from+align_nr));
			mmc_add_skip_space(skip_space, skip, from, nr);
		} else {
			if (align_from - from)
				mmc_add_skip_space(skip_space, skip++, from, (align_from-from));

			if (skip)
				last_skip_len = skip_space[2];
			else
				last_skip_len = 0;
			if (nr - align_nr - last_skip_len)
				mmc_add_skip_space(skip_space, skip++, (align_from+align_nr), (nr-align_nr-last_skip_len));
		}
	}

	return ret;
}

int mmc_do_secure_wipe(struct mmc *mmc, unsigned int from, unsigned int nr,
	unsigned int *skip_space)
{
	int ret = 0;
	int skip, not_support_wipe = 0;


	MMCINFO("+++%s\n", __FUNCTION__);

	if (nr == 0) {
		MMCINFO("%s: on space need to erase, nr %d\n", __FUNCTION__, nr);
		return 0;
	}

	if (IS_SD(mmc)) {
		MMCINFO("%s: no mmc, do nothing\n", __FUNCTION__);
		ret = -2;
		goto ERR_RET;
	}

	skip = 0;
	skip_space[0] = 0x0;

	if (mmc->version <= MMC_VERSION_4_41) //ver 4.41 or older
	{
		if (mmc->secure_feature & EXT_CSD_SEC_ER_EN)
		{
			//support secure purge operation
			if (mmc->secure_feature & EXT_CSD_SEC_GB_CL_EN) {
				//support trim
				MMCDBG("%d %s: start secure trim...\n", __LINE__, __FUNCTION__);
				ret = mmc_erase(mmc, from, nr, MMC_SECURE_TRIM1_ARG);
				if (ret) {
					MMCINFO("secure trim failed, range %d - %d \n",
						from, (from+nr));
					mmc_add_skip_space(skip_space, skip, from, nr);
				}
			} else {
				ret = mmc_insecure_secure_erase(mmc, from, nr, skip_space, 1);
			}
		}
		else if (mmc->secure_feature & EXT_CSD_SEC_GB_CL_EN)
		{
			//support insecure trim operation
			MMCDBG("%d %s: start trim...\n", __LINE__, __FUNCTION__);
			ret = mmc_erase(mmc, from, nr, MMC_TRIM_ARG);
			if (ret) {
				MMCINFO("trim failed, range %d - %d \n", from, (from+nr));
				mmc_add_skip_space(skip_space, skip, from, nr);
			}
		}
		else
		{
			//is currently not an acceptable solution. writing of zeroes to the user data partition as a third option
			MMCINFO("no method to wipe data (emmc <= v4.41)!\n ");
			not_support_wipe = 1;
			mmc_add_skip_space(skip_space, skip, from, nr);
		}
	}
	else if (mmc->version <= MMC_VERSION_5_0) //v4.5 or newer
	{
		if (mmc->secure_feature & EXT_CSD_SEC_SANITIZE)
		{
			//support sanitize
			if (mmc->secure_feature & EXT_CSD_SEC_GB_CL_EN) {
				//support trim
				MMCDBG("%d %s: start trim...\n", __LINE__, __FUNCTION__);
				ret = mmc_erase(mmc, from, nr, MMC_TRIM_ARG);
				if (ret) {
					MMCINFO("trim failed, range %d - %d \n", from, (from+nr));
					mmc_add_skip_space(skip_space, skip, from, nr);
					goto ERR_RET;
				}
			} else {
				ret = mmc_insecure_secure_erase(mmc, from, nr, skip_space, 0);
				if (ret) {
					MMCINFO("erase failed, range %d - %d \n", from, (from+nr));
					goto ERR_RET;
				}
			}

			MMCDBG("%d %s: start sanitize...\n", __LINE__, __FUNCTION__);
			ret = mmc_do_sanitize(mmc);
			if (ret) {
				MMCINFO("do sanitize failed!!\n");
				skip = 0;
				skip_space[0] = 0x0;
				mmc_add_skip_space(skip_space, skip, from, nr);
			}
		}
		else
		{
			//If the eMMC 4.5 part does not expose the required command set, there is currently not an acceptable solution to sanitize this part for re-use
			not_support_wipe = 1;
			MMCINFO("no method to wipe data for current (emmc >v4.5)!\n ");
			mmc_add_skip_space(skip_space, skip, from, nr);
		}
	}
	else
	{
		MMCINFO("Unknown mmc version 0x%x\n", mmc->version);
		ret = -3;
	}

	if (not_support_wipe)
		ret = -2;

ERR_RET:

	MMCINFO("---%s ret %d\n", __FUNCTION__, ret);
	return ret;
}

int mmc_secure_wipe(int dev_num, unsigned int start,
	unsigned int blkcnt, unsigned int *skip_space)
{
	int ret = 0;
	struct mmc *mmc = find_mmc_device(dev_num);

	MMCINFO("========start %s\n", __FUNCTION__);
	if (mmc->drv_wipe_feature & DRV_PARA_DISABLE_SECURE_WIPE) {
		MMCINFO("driver do not support secure wipe operation\n");
		return -1;
	}

	ret = mmc_do_secure_wipe(mmc, start, blkcnt, skip_space);
	if (ret == -1) {
		MMCINFO("erase failed!!!!!!\n");
	} else if ((ret == -2) || (ret == -3)) {
		MMCINFO("do not erase!!!!!!\n");
		ret = -1;
	} else if (skip_space[0]){
		MMCINFO("skip some space when align erase group, need to write zeros.\n");
		ret = 1;
	} else {
		MMCINFO("erase ok\n");
		ret = 0;
	}

	MMCINFO("========end %s %d\n", __FUNCTION__, ret);
	return ret;
}

int mmc_mmc_erase(int dev_num, unsigned int start,
	unsigned int blkcnt, unsigned int *skip_space)
{
	struct mmc *mmc = find_mmc_device(dev_num);
	int i, ret1, ret = 0;

	MMCDBG("start %s ...\n", __FUNCTION__);
	if (IS_SD(mmc)) {
		MMCINFO("%s: sd card don't support erase\n", __FUNCTION__);
		ret = -1;
		goto ERR_RET;
	}

	if (mmc->drv_erase_feature & DRV_PARA_DISABLE_EMMC_ERASE) {
		MMCINFO("%s: driver don't support erase\n", __FUNCTION__);
		ret = -1;
		goto ERR_RET;
	}

	if (blkcnt == 0) {
		MMCINFO("%s: no space need to erase, from:%d nr:%d\n",
			__FUNCTION__, start, blkcnt);
		ret = 0;
		goto ERR_RET;
	}

	if ((start+blkcnt) > mmc->block_dev.lba) {
		MMCINFO("%s: input lenght error!!!\n", __FUNCTION__);
		blkcnt = mmc->block_dev.lba - start;
		MMCINFO("%s: after clip, from: %d, nr: %d\n",
			__FUNCTION__, start, blkcnt);
	}

	ret = mmc_insecure_secure_erase(mmc, start, blkcnt, skip_space, 0);
	if (ret) {
		MMCINFO("%s: erase emmc fail!\n", __FUNCTION__);
	}

	if (skip_space[0]) {
		ret = 1;

		MMCINFO("%s: some sectors in emmc are ignored!\n", __FUNCTION__);
		for (i=0; i<2; i++)
			if (skip_space[0] & (1<<i))
				MMCINFO("--%d: from%d  nr%d \n", i,
					(int)skip_space[i*2+1], (int)skip_space[i*2+2]);
	}

	if ((mmc->drv_erase_feature & DRV_PARA_ENABLE_EMMC_SANITIZE_WHEN_ERASE)
		&& (mmc->secure_feature & EXT_CSD_SEC_SANITIZE))
	{
		ret1 = mmc_do_sanitize(mmc);
		if (ret1) {
			MMCINFO("%s: emmc sanitize fail. ignore this error and continue...\n", __FUNCTION__);
		}
	}

ERR_RET:
	MMCDBG("end %s %d\n", __FUNCTION__, ret);
	return ret;
}

int mmc_mmc_sanitize(int dev_num)
{
	struct mmc *mmc = find_mmc_device(dev_num);
	int ret = 0;

	MMCDBG("start %s ...\n", __FUNCTION__);
	if (IS_SD(mmc)) {
		MMCINFO("%s: sd card don't support erase\n", __FUNCTION__);
		ret = -1;
		goto ERR_RET;
	}

	if (!(mmc->secure_feature & EXT_CSD_SEC_SANITIZE)) {
		MMCINFO("%s: driver don't support sanitize\n", __FUNCTION__);
		ret = -1;
		goto ERR_RET;
	}

	ret = mmc_do_sanitize(mmc);
	if (ret) {
		ret = -1;
		MMCINFO("%s: sanitize fail!\n", __FUNCTION__);
	}

ERR_RET:
	MMCDBG("end %s %d\n", __FUNCTION__, ret);
	return ret;
}

int mmc_mmc_trim(int dev_num, unsigned int start, unsigned int blkcnt)
{
	struct mmc *mmc = find_mmc_device(dev_num);
	int ret = 0;

	MMCDBG("start %s ...\n", __FUNCTION__);
	if (IS_SD(mmc)) {
		MMCINFO("%s: sd card don't support trim\n", __FUNCTION__);
		ret = -1;
		goto ERR_RET;
	}

	if (blkcnt == 0) {
		MMCINFO("%s: no space need to erase, from:%d nr:%d\n",
			__FUNCTION__, start, blkcnt);
		ret = 0;
		goto ERR_RET;
	}

	if ((start+blkcnt) > mmc->block_dev.lba) {
		MMCINFO("%s: input lenght error!!!\n", __FUNCTION__);
		blkcnt = mmc->block_dev.lba - start;
		MMCINFO("%s: after clip, from: %d, nr: %d\n",
			__FUNCTION__, start, blkcnt);
	}

	if (mmc->secure_feature & EXT_CSD_SEC_GB_CL_EN)
	{
		ret = mmc_erase(mmc, start, blkcnt, MMC_TRIM_ARG);
		if (ret) {
			MMCINFO("trim failed, range %d - %d\n",	start, (start+blkcnt));
		}
	} else {
		MMCINFO("%s: don't support trim!\n", __FUNCTION__);
		ret = -1;
	}

ERR_RET:
	MMCDBG("end %s %d\n", __FUNCTION__, ret);
	return ret;
}

int mmc_mmc_discard(int dev_num, unsigned int start, unsigned int blkcnt)
{
	struct mmc *mmc = find_mmc_device(dev_num);
	int ret = 0;

	MMCDBG("start %s ...\n", __FUNCTION__);
	if (IS_SD(mmc)) {
		MMCINFO("%s: sd card don't support discard\n", __FUNCTION__);
		ret = -1;
		goto ERR_RET;
	}

	if (blkcnt == 0) {
		MMCINFO("%s: no space need to erase, from:%d nr:%d\n",
			__FUNCTION__, start, blkcnt);
		ret = 0;
		goto ERR_RET;
	}

	if ((start+blkcnt) > mmc->block_dev.lba) {
		MMCINFO("%s: input lenght error!!!\n", __FUNCTION__);
		blkcnt = mmc->block_dev.lba - start;
		MMCINFO("%s: after clip, from: %d, nr: %d\n",
			__FUNCTION__, start, blkcnt);
	}

	/* eMMC v4.5 or later */
	if (mmc->version >= MMC_VERSION_4_5)
	{
		ret = mmc_erase(mmc, start, blkcnt, MMC_DISCARD_ARG);
		if (ret) {
			MMCINFO("trim failed, range %d - %d\n",	start, (start+blkcnt));
		}
	} else {
		MMCINFO("%s: don't support discard!\n", __FUNCTION__);
		ret = -1;
	}

ERR_RET:
	MMCDBG("end %s %d\n", __FUNCTION__, ret);
	return ret;
}

int mmc_mmc_secure_erase(int dev_num, unsigned int start,
	unsigned int blkcnt, unsigned int *skip_space)
{
	struct mmc *mmc = find_mmc_device(dev_num);
	int i, ret = 0;

	MMCDBG("start %s ...\n", __FUNCTION__);
	if (IS_SD(mmc)) {
		MMCINFO("%s: sd card don't support secure erase!\n", __FUNCTION__);
		ret = -1;
		goto ERR_RET;
	}

	if (blkcnt == 0) {
		MMCINFO("%s: no space need to erase, from:%d nr:%d\n",
			__FUNCTION__, start, blkcnt);
		ret = 0;
		goto ERR_RET;
	}

	if ((start+blkcnt) > mmc->block_dev.lba) {
		MMCINFO("%s: input lenght error!!!\n", __FUNCTION__);
		blkcnt = mmc->block_dev.lba - start;
		MMCINFO("%s: after clip, from: %d, nr: %d\n",
			__FUNCTION__, start, blkcnt);
	}

	if (!(mmc->secure_feature & EXT_CSD_SEC_ER_EN)) {
		MMCINFO("%s: don't support secure erase!\n", __FUNCTION__);
		ret = -1;
		goto ERR_RET;
	}

	ret = mmc_insecure_secure_erase(mmc, start, blkcnt, skip_space,1);
	if (ret) {
		MMCINFO("%s: erase emmc fail!\n", __FUNCTION__);
	}

	if (skip_space[0]) {
		MMCDBG("%s: some sectors in emmc are ignored!\n\n", __FUNCTION__);
		for (i=0; i<2; i++)
			if (skip_space[0] & (1<<i))
				MMCDBG("--%d: from%d  nr%d \n",
					skip_space[i*2+1], skip_space[i*2+2]);
	}

ERR_RET:
	MMCDBG("end %s %d\n", __FUNCTION__, ret);
	return ret;
}

int mmc_mmc_secure_trim(int dev_num, unsigned int start, unsigned int blkcnt)
{
	struct mmc *mmc = find_mmc_device(dev_num);
	int ret = 0;

	MMCDBG("start %s ...\n", __FUNCTION__);
	if (IS_SD(mmc)) {
		MMCINFO("%s: sd card don't support secure trim!\n", __FUNCTION__);
		ret = -1;
		goto ERR_RET;
	}

	if (blkcnt == 0) {
		MMCINFO("%s: no space need to erase, from:%d nr:%d\n",
			__FUNCTION__, start, blkcnt);
		ret = 0;
		goto ERR_RET;
	}

	if ((start+blkcnt) > mmc->block_dev.lba) {
		MMCINFO("%s: input lenght error!!!\n", __FUNCTION__);
		blkcnt = mmc->block_dev.lba - start;
		MMCINFO("%s: after clip, from: %d, nr: %d\n",
			__FUNCTION__, start, blkcnt);
	}

	if ((mmc->secure_feature & EXT_CSD_SEC_ER_EN)
		&& (mmc->secure_feature & EXT_CSD_SEC_GB_CL_EN))
	{
		ret = mmc_erase(mmc, start, blkcnt, MMC_SECURE_TRIM1_ARG);
		if (ret) {
			MMCINFO("secure trim failed, range %d - %d\n",	start, (start+blkcnt));
		}
	} else {
		MMCINFO("%s: don't support secure trim!\n", __FUNCTION__);
		ret = -1;
	}

ERR_RET:
	MMCDBG("end %s %d\n", __FUNCTION__, ret);
	return ret;
}

#if 0
/* only clear first 128KB of boot part 0 to zeros */
int mmc_mmc_clear_boot_part1(int dev_num)
{
	struct mmc *mmc = find_mmc_device(dev_num);
	int err = 0;
	void *src, *dst;
	unsigned int blkcnt = 128 * 1024 * 2; //128KB

	if (!(mmc->boot_support))
	{
		MMCINFO("Card doesn't support boot part\n");
		return 0;
	}

	src = malloc(blkcnt * mmc->write_bl_len);
	if (src == NULL) {
		MMCINFO("%s: malloc mem failed\n", __FUNCTION__);
		return -1;
	}
	memset(src, 0, blkcnt * mmc->write_bl_len);

	dst = malloc(blkcnt * mmc->write_bl_len);
	if (dst == NULL){
		MMCINFO("%s: malloc mem failed\n", __FUNCTION__);
		goto ERR_RET1;
	}

	err = mmc_switch_boot_bus_cond(dev_num,
								MMC_SWITCH_BOOT_SDR_NORMAL,
								MMC_SWITCH_BOOT_RST_BUS_COND,
								MMC_SWITCH_BOOT_BUS_SDRx4_DDRx4);
	if (err) {
		MMCINFO("mmc switch boot bus condition failed\n");
		goto ERR_RET;
	}
	MMCDBG("mmc switch boot bus condition succeed\n");

	err = mmc_switch_boot_part(dev_num,
								MMC_SWITCH_PART_BOOT_ACK_ENB,
								MMC_SWITCH_PART_BOOT_PART_1);
	if (err) {
		MMCINFO("mmc switch boot part failed\n");
		err = -1;
		goto ERR_RET;
	}
	MMCDBG("mmc switch boot part succeed\n");


	//switch to boot partition 1
	if (mmc_switch_part(dev_num, MMC_SWITCH_PART_BOOT_PART_1)) {
		MMCINFO("switch to boot1 partition failed\n");
		err = -1;
		goto ERR_RET;
	}

	mmc_bwrite(dev_num, 0, blkcnt, src);
	mmc_bread(dev_num, 0, blkcnt, dst);
	if (memcmp(src, dst, blkcnt*mmc->write_bl_len))
		err = -1;

	//switch back to user partiton 1
	if (mmc_switch_part(dev_num,  0)) {
		MMCINFO("switch to boot1 partition failed\n");
		err = -1;
	}

ERR_RET:
	free(dst);

ERR_RET1:
	free(src);

	return err;
}

static unsigned long
mmc_berase_mass_pro(int dev_num)
{
	int i, ret = 0, boot_ret;
	struct mmc *mmc = find_mmc_device(dev_num);
	unsigned long tmp_skip_space[1+2*2] = {0};

	if (!IS_SD(mmc))
	{
		//erase boot part
		boot_ret = mmc_mmc_clear_boot_part1(dev_num);
		if (boot_ret) {
			MMCINFO("%s: erase boot part 1 fail\n", __FUNCTION__);
		}

		//erase user part
		ret = _mmc_insecure_secure_erase(mmc, 0, mmc->block_dev.lba, tmp_skip_space, 0);
		if (ret) {
			MMCINFO("%s: erase emmc user part fail!\n", __FUNCTION__);
		}

		if (tmp_skip_space[0]) {
			MMCINFO("%s: some sectors in emmc part are ignored!\n\n", __FUNCTION__);
			for (i=0; i<2; i++)
				if (tmp_skip_space[0] & (1<<i))
					MMCINFO("--%d: from%d  nr%d \n",
						tmp_skip_space[i*2+1], tmp_skip_space[i*2+2]);
		}
	}
	else
	{
		MMCINFO("%s: don't support SD card\n", __FUNCTION__);
		ret = -1;
	}

	return (ret | boot_ret);
}
#endif

int mmc_send_manual_stop(struct mmc *mmc)
{
	struct mmc_cmd cmd;
	int ret = 0;
	cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
	cmd.cmdarg = 0;
	cmd.resp_type = MMC_RSP_R1b;
	cmd.flags = MMC_CMD_MANUAL;//let bsp send cmd12
	ret = mmc_send_cmd(mmc, &cmd, NULL);
	if (ret) {
		MMCINFO("mmc fail to send manual stop cmd\n");
		return ret;
	}
	return 0;
}

struct mmc *find_mmc_device(int dev_num)
{
	struct mmc *m;
	struct list_head *entry;

	list_for_each(entry, &mmc_devices) {
		m = list_entry(entry, struct mmc, link);

		if (m->block_dev.dev == dev_num)
			return m;
	}

	MMCINFO("MMC Device %d not found\n", dev_num);

	return NULL;
}

//static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
//{
//	struct mmc_cmd cmd;
//	ulong end;
//	int err, start_cmd, end_cmd;
//
//	if (mmc->high_capacity)
//		end = start + blkcnt - 1;
//	else {
//		end = (start + blkcnt - 1) * mmc->write_bl_len;
//		start *= mmc->write_bl_len;
//	}
//
//	if (IS_SD(mmc)) {
//		start_cmd = SD_CMD_ERASE_WR_BLK_START;
//		end_cmd = SD_CMD_ERASE_WR_BLK_END;
//	} else {
//		start_cmd = MMC_CMD_ERASE_GROUP_START;
//		end_cmd = MMC_CMD_ERASE_GROUP_END;
//	}
//
//	cmd.cmdidx = start_cmd;
//	cmd.cmdarg = start;
//	cmd.resp_type = MMC_RSP_R1;
//	cmd.flags = 0;
//
//	err = mmc_send_cmd(mmc, &cmd, NULL);
//	if (err)
//		goto err_out;
//
//	cmd.cmdidx = end_cmd;
//	cmd.cmdarg = end;
//
//	err = mmc_send_cmd(mmc, &cmd, NULL);
//	if (err)
//		goto err_out;
//
//	cmd.cmdidx = MMC_CMD_ERASE;
//	cmd.cmdarg = SECURE_ERASE;
//	cmd.resp_type = MMC_RSP_R1b;
//
//	err = mmc_send_cmd(mmc, &cmd, NULL);
//	if (err)
//		goto err_out;
//
//	return 0;
//
//err_out:
//	puts("mmc erase failed\n");
//	return err;
//}


static unsigned long
mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
{
	int err = 0;
	struct mmc *mmc = find_mmc_device(dev_num);
//	unsigned blk = 0, blk_r = 0;
	void* src = malloc(blkcnt * mmc->write_bl_len);
	if(src == NULL){
		printf("erase malloc failed\n");
		return -1;
	}

	if (!mmc){
		MMCINFO("Can not find mmc dev\n");
		free(src);
		return -1;
	}

	memset(src, 0, mmc->write_bl_len*blkcnt);
	MMCINFO("erase blk %ld ~ %ld\n", start, start + blkcnt - 1);
	err = mmc_bwrite(dev_num, start, blkcnt, src);
	//mmcinfo("erase flag%d",err);
	if(!err){
		MMCINFO("erase failed\n");
	}

	free(src);
	return err;
	/*
	if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
		mmcdbg("\n\nCaution! Your devices Erase group is 0x%x\n"
			"The erase range would be change to 0x%x~0x%x\n\n",
		       mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
		       ((start + blkcnt + mmc->erase_grp_size)
		       & ~(mmc->erase_grp_size - 1)) - 1);

	while (blk < blkcnt) {
		blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
			mmc->erase_grp_size : (blkcnt - blk);
		err = mmc_erase_t(mmc, start + blk, blk_r);
		if (err)
			break;

		blk += blk_r;
	}
	return blk;
	*/
}

#if defined(CONFIG_ARCH_SUN8IW5P1) || defined(CONFIG_ARCH_SUN8IW6P1) || defined(CONFIG_ARCH_SUN8IW8P1)||(defined CONFIG_ARCH_SUN8IW7P1)
/*
 * 1. 18=3*6, each phase config try 3 times; don't try tx phase 2.
 * 2. {1,1} is the best phase config to compile most of emmc
 * 3. if retry ok, keep current phase and exit. use this new phase config for following operation.
 *    if retry fail, set phase to defaul value.
 */
#define MAX_RETRY_CNT 18
static int mmc_retry_request(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
	//char sunxi_phase[9][2]={{1,1},{0,0},{1,0},{0,1},{1,2},{0,2},{2,0},{2,1},{2,2}};
	char sunxi_phase[9][2]={{1,1},{0,0},{1,0},{0,1},{1,2},{0,2}};
	//char sunxi_phase[9][2]={{0,1},  {1,1},{0,0},{1,0},   {1,2},{0,2}};
	int retry_cnt;
	int ret, err = 0;
	u32 timeout = 1000;

	if (!mmc->set_phase) {
		return -1;
	}

	/* send manual stop */
	mmc_send_manual_stop(mmc);
	/* Waiting for the ready status */
	mmc_send_status(mmc, timeout);

	retry_cnt = 0;
	do
	{
		/* set phase */
		ret = mmc->set_phase(mmc, sunxi_phase[retry_cnt/3][0], sunxi_phase[retry_cnt/3][1]);
		if (ret) {
			MMCINFO("set phase fail, retry fail\n");
			err = -1;
			break;
		}

		/* retry */
		err = mmc->send_cmd(mmc, cmd, data);
		if (!err) {
			/* if retry ok, keep current phase and exit. */
			MMCINFO("retry ok! retry cnt %d\n", retry_cnt);
			break;
		} else {
			/* send manual stop */
			mmc_send_manual_stop(mmc);
			/* Waiting for the ready status */
			mmc_send_status(mmc, timeout);
		}

		retry_cnt++;
	} while (retry_cnt < MAX_RETRY_CNT);

	/* reset to default phase if retry fail */
	if (err)
	{
		mmc->set_phase(mmc, sunxi_phase[0][0], sunxi_phase[0][1]);
		if (ret) {
			MMCINFO("retry fail, set phase to default fail\n");
		}
	}

	return err;
}
#endif

static ulong
mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
{
	struct mmc_cmd cmd;
	struct mmc_data data;
	int timeout = 1000;

	if ((start + blkcnt) > mmc->block_dev.lba) {
		MMCINFO("MMC: block number 0x%lx exceeds max(0x%lx)\n",
			start + blkcnt, mmc->block_dev.lba);
		return 0;
	}

	if (blkcnt > 1)
		cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
	else
		cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;

	if (mmc->high_capacity)
		cmd.cmdarg = start;
	else
		cmd.cmdarg = start * mmc->write_bl_len;

	cmd.resp_type = MMC_RSP_R1;
	cmd.flags = 0;

	data.src = src;
	data.blocks = blkcnt;
	data.blocksize = mmc->write_bl_len;
	data.flags = MMC_DATA_WRITE;

	if (mmc_send_cmd(mmc, &cmd, &data)) {
		MMCINFO("mmc write failed\n");

		#if defined(CONFIG_ARCH_SUN8IW5P1) || \
			defined(CONFIG_ARCH_SUN8IW6P1) || \
			defined (CONFIG_ARCH_SUN8IW8P1)|| \
			(defined CONFIG_ARCH_SUN8IW7P1)

		MMCINFO("mmc write: start retry....\n");
		if (mmc_retry_request(mmc, &cmd, &data)) {
			MMCINFO("mmc write: retry fail\n");
			return 0;
		} else {
			MMCINFO("mmc write: retry ok\n");
		}

		#else

		return 0;

		#endif
	}

	/* SPI multiblock writes terminate using a special
	 * token, not a STOP_TRANSMISSION request.
	 */
	if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
		cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
		cmd.cmdarg = 0;
		cmd.resp_type = MMC_RSP_R1b;
		cmd.flags = 0;
		if (mmc_send_cmd(mmc, &cmd, NULL)) {
			MMCINFO("mmc fail to send stop cmd\n");
			return 0;
		}
    }
    /* Waiting for the ready status */
    mmc_send_status(mmc, timeout);

	return blkcnt;
}

static ulong
mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
{
	lbaint_t cur, blocks_todo = blkcnt;

	struct mmc *mmc = find_mmc_device(dev_num);

	if (blkcnt == 0){
		MMCINFO("blkcnt should not be 0\n");
		return 0;
	}
	if (!mmc){
		MMCINFO("Can not found device\n");
		return 0;
	}

	if (mmc_set_blocklen(mmc, mmc->write_bl_len)){
		MMCINFO("set block len failed\n");

		return 0;
	}

	do {
		cur = (blocks_todo > mmc->b_max) ?  mmc->b_max : blocks_todo;
		if(mmc_write_blocks(mmc, start, cur, src) != cur){
			MMCINFO("write block failed\n");
			return 0;
		}
		blocks_todo -= cur;
		start += cur;
//		src += cur * mmc->write_bl_len;
		src = (char*)src + cur * mmc->write_bl_len;
	} while (blocks_todo > 0);

	return blkcnt;
}


static ulong
mmc_bwrite_mass_pro(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
{
	lbaint_t blocks_do = 0;
	ulong start_todo = start;

	signed int err = 0;
	struct mmc *mmc = find_mmc_device(dev_num);
#ifdef USE_EMMC_BOOT_PART
	MMCINFO("mmc start mass pro boot part...\n");
	do{
		if((start != BOOT0_SDMMC_START_ADDR)) {
			MMCINFO("boot0 start address %d\n", start);
			break;
		}

		if (!(mmc->boot_support)) //!(mmc->part_support & PART_SUPPORT)
		{
			MMCINFO("Card doesn't support boot part\n");
			break;
		}


		err = mmc_switch_boot_bus_cond(dev_num, MMC_SWITCH_BOOT_SDR_NORMAL, MMC_SWITCH_BOOT_RST_BUS_COND, MMC_SWITCH_BOOT_BUS_SDRx4_DDRx4);
		if (err) {
			MMCINFO("mmc switch boot bus condition failed\n");
			return err;
		}
		MMCDBG("mmc switch boot bus condition succeed\n");

		err = mmc_switch_boot_part(dev_num, MMC_SWITCH_PART_BOOT_ACK_ENB, MMC_SWITCH_PART_BOOT_PART_1);
		if (err) {
			MMCINFO("mmc switch boot part failed\n");
			return err;
		}
		MMCDBG("mmc switch boot part  succeed\n");

	}while(0);
#else
	do{
		if((start != BOOT0_SDMMC_START_ADDR)) {
			MMCINFO("boot0 start address %d\n", start);
			break;
		}

		if (!(mmc->boot_support)) //!(mmc->part_support & PART_SUPPORT)
		{
			MMCINFO("Card doesn't support boot part\n");
			break;
		}

		err = mmc_switch_boot_part(dev_num, 0, MMC_SWITCH_PART_BOOT_PART_NONE);	//disable boot mode
		if (err) {
			MMCINFO("mmc disable boot mode failed\n");
			return err;
		}
		MMCDBG("mmc disable boot mode succeed\n");
	}while(0);

#endif


#ifdef USE_EMMC_BOOT_PART

	//write boot0.bin to boot partition
	if ( (mmc->boot_support) && (start == BOOT0_SDMMC_START_ADDR) )//(mmc->part_support & PART_SUPPORT)
	{
		if (mmc_switch_part(dev_num, MMC_SWITCH_PART_BOOT_PART_1)) {
			MMCINFO("switch to boot1 partition failed\n");
			return 0;
		}
		//In eMMC boot partition,boot0.bin start from 0 sector,so we must change start form 16 to 0;
		start_todo= 0;
	}
#endif

	blocks_do = mmc_bwrite(dev_num, start_todo, blkcnt, src);
	//check boot0
	if(start == BOOT0_SDMMC_START_ADDR){
		u32  rblk = 0;
		s32 err = 0;
		void *dst = malloc(blkcnt * mmc->write_bl_len);
		MMCDBG("try to check boot0\n");
		if(dst == NULL){
			MMCINFO("malloc mem failed\n");
			return 0;
		}
		rblk = mmc_bread(dev_num, start_todo, blkcnt, dst);
		if(rblk){
			if(memcmp(src,dst,blkcnt * mmc->write_bl_len)){
				err = -1;
			}
		}else{
			err = -1;
		}
		free(dst);
		if(err){
			MMCINFO("check boot0 failded\n");
			return 0;
		}
		MMCDBG("check boot0 ok\n");

	}

#ifdef USE_EMMC_BOOT_PART
	//
	if ((mmc->boot_support)  && (start == BOOT0_SDMMC_START_ADDR) )//(mmc->part_support & PART_SUPPORT)
	{
		//switch back to user partiton
		if (mmc_switch_part(dev_num,  0)) {
			MMCINFO("switch to boot1 partition failed\n");
			return 0;
		}
#ifdef USE_EMMC_USER_WHEN_USE_BOOT_PART//use eMMC boot and user part at the same time
		MMCINFO("mmc start write user part after write boot part...\n");
		blocks_do = mmc_bwrite(dev_num, start, blkcnt, src);
		//check boot0
		{
			u32  rblk = 0;
			s32 err = 0;
			void *dst = malloc(blkcnt * mmc->write_bl_len);
			MMCDBG("try to check boot0 in user part when use eMMC boot and user part at the same time\n");
			if(dst == NULL){
				MMCINFO("malloc mem failed\n");
				return 0;
			}
			rblk = mmc_bread(dev_num, start, blkcnt, dst);
			if(rblk){
				if(memcmp(src,dst,blkcnt * mmc->write_bl_len)){
					err = -1;
			}
			}else{
				err = -1;
			}
			free(dst);
			if(err){
				MMCINFO("check boot0 in user part failded when use eMMC boot and user part at the same time\n");
				return 0;
			}
			MMCDBG("check boot0 in user part ok when use eMMC boot and user part at the same time\n");
	}


#endif
	}
#endif
	return blocks_do;

}




int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
{
	struct mmc_cmd cmd;
	struct mmc_data data;
	int timeout = 1000;

	if (blkcnt > 1)
		cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
	else
		cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
	if (mmc->high_capacity)
		cmd.cmdarg = start;
	else
		cmd.cmdarg = start * mmc->read_bl_len;
	cmd.resp_type = MMC_RSP_R1;
	cmd.flags = 0;

	data.dest = dst;
	data.blocks = blkcnt;
	data.blocksize = mmc->read_bl_len;
	data.flags = MMC_DATA_READ;

	if (mmc_send_cmd(mmc, &cmd, &data)) {
		MMCINFO(" read block failed\n");

		#if defined(CONFIG_ARCH_SUN8IW5P1) || \
			defined(CONFIG_ARCH_SUN8IW6P1) || \
			defined (CONFIG_ARCH_SUN8IW8P1)|| \
			(defined CONFIG_ARCH_SUN8IW7P1)

		MMCINFO("mmc read: start retry....\n");
		if (mmc_retry_request(mmc, &cmd, &data)) {
			MMCINFO("mmc read: retry fail\n");
			return 0;
		} else {
			MMCINFO("mmc read: retry ok\n");
		}

		#else

		return 0;

		#endif
	}

	if (blkcnt > 1) {
		cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
		cmd.cmdarg = 0;
		cmd.resp_type = MMC_RSP_R1b;
		cmd.flags = 0;
		if (mmc_send_cmd(mmc, &cmd, NULL)) {
			MMCINFO("mmc fail to send stop cmd\n");
			return 0;
		}

		/* Waiting for the ready status */
		mmc_send_status(mmc, timeout);
	}

	return blkcnt;
}

static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
{
	lbaint_t cur, blocks_todo = blkcnt;

	if (blkcnt == 0){
		MMCINFO("blkcnt should not be 0\n");
		return 0;
	}
	struct mmc *mmc = find_mmc_device(dev_num);
	if (!mmc){
		MMCINFO("Can not find mmc dev\n");
		return 0;
	}
	if ((start + blkcnt) > mmc->block_dev.lba) {
		MMCINFO("MMC: block number 0x%lx exceeds max(0x%lx)\n",
			start + blkcnt, mmc->block_dev.lba);
		return 0;
	}


	if (mmc_set_blocklen(mmc, mmc->read_bl_len)){
		MMCINFO("Set block len failed\n");
		return 0;
	}

	do {
		cur = (blocks_todo > mmc->b_max) ?  mmc->b_max : blocks_todo;
		if(mmc_read_blocks(mmc, dst, start, cur) != cur){
			MMCINFO("block read failed\n");
			return 0;
		}
		blocks_todo -= cur;
		start += cur;
//		dst += cur * mmc->read_bl_len;
		dst = (char*)dst + cur * mmc->read_bl_len;
	} while (blocks_todo > 0);

	return blkcnt;
}

static ulong mmc_bread_mass_pro(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
{
	lbaint_t blocks_do = 0;
	ulong start_todo = start;

#ifdef USE_EMMC_BOOT_PART
	struct mmc *mmc = find_mmc_device(dev_num);
	//write boot0.bin to boot partition
	if ((mmc->boot_support)  && (start == BOOT0_SDMMC_START_ADDR) )//(mmc->part_support & PART_SUPPORT)
	{
		if (mmc_switch_part(dev_num, MMC_SWITCH_PART_BOOT_PART_1))
		{
			MMCINFO("switch to boot1 partition failed\n");
			return 0;
		}
		//In eMMC boot partition,boot0.bin start from 0 sector,so we must change start form 16 to 0;
		start_todo= 0;
	}
#endif

	blocks_do = mmc_bread(dev_num, start_todo, blkcnt, dst);

#ifdef USE_EMMC_BOOT_PART
	//
	if ( (mmc->boot_support) && (start == BOOT0_SDMMC_START_ADDR) )//(mmc->part_support & PART_SUPPORT)
	{
		//switch back to user partiton
		if (mmc_switch_part(dev_num,  0)) {
			MMCINFO("switch to boot1 partition failed\n");
			return 0;
		}
	}
#endif

	return blocks_do;
}

#ifdef CONFIG_SUNXI_SECURE_STORAGE

static int check_secure_area(ulong start, lbaint_t blkcnt)
{
	u32 sta_add = start;
	u32 end_add = start + blkcnt -1;
	u32 se_sta_add = SDMMC_SECURE_STORAGE_START_ADD;
	u32 se_end_add = SDMMC_SECURE_STORAGE_START_ADD+(SDMMC_ITEM_SIZE*2*MAX_SECURE_STORAGE_MAX_ITEM)-1;
	if(blkcnt<=(SDMMC_ITEM_SIZE*2*MAX_SECURE_STORAGE_MAX_ITEM)){
		if(((sta_add >= se_sta_add)&&(sta_add <= se_end_add))
			||((end_add >= se_sta_add)&&(end_add <= se_end_add))){
			return 1;
		}
	}else{
		if(((se_sta_add >= sta_add)&&(se_sta_add <= end_add))
			||((se_end_add >= sta_add)&&(se_end_add <= end_add))){
			return 1;
		}
	}

	return 0;
}


static ulong
mmc_bwrite_mass_pro_secure(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
{
	if(check_secure_area(start,blkcnt)){
		MMCINFO("Should not w/r secure area in fun %s,line,%d in start %d,end %d\n",\
			__FUNCTION__,__LINE__ ,start,start + blkcnt-1);
		return -1;
	}

	return mmc_bwrite_mass_pro(dev_num, start, blkcnt, src);
}

static ulong mmc_bread_mass_pro_secure(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
{
	if(check_secure_area(start,blkcnt)){
		MMCINFO("Should not w/r secure area in fun %s,line,%d in start %d,end %d\n",\
			__FUNCTION__,__LINE__ ,start,start + blkcnt-1);
		return -1;
	}

	return mmc_bread_mass_pro(dev_num, start, blkcnt, dst);
}

static unsigned long
mmc_berase_secure(int dev_num, unsigned long start, lbaint_t blkcnt)
{
	if(check_secure_area(start,blkcnt)){
		MMCINFO("Should not w/r secure area in fun %s,line,%d in start %d,end %d\n",\
			__FUNCTION__,__LINE__ ,start,start + blkcnt-1);
		return -1;
	}

	return mmc_berase(dev_num, start, blkcnt);
}

int mmc_secure_wipe_secure(int dev_num, unsigned int start, unsigned int blkcnt, unsigned int *skip_space)
{
	if(check_secure_area(start,blkcnt)){
		MMCINFO("Should not w/r secure area in fun %s,line,%d in start %d,end %d\n",\
			__FUNCTION__,__LINE__ ,start,start + blkcnt-1);
		return -1;
	}

	return mmc_secure_wipe(dev_num, start, blkcnt, skip_space);
}

static ulong mmc_bread_secure(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
{
	if(check_secure_area(start,blkcnt)){
		MMCINFO("Should not w/r secure area in fun %s,line,%d in start %d,end %d\n",\
			__FUNCTION__,__LINE__ ,start,start + blkcnt-1);
		return -1;
	}

	return mmc_bread(dev_num, start, blkcnt, dst);
}

int mmc_mmc_erase_secure(int dev_num, unsigned int start, unsigned int blkcnt, unsigned int *skip_space)
{
	if(check_secure_area(start,blkcnt)){
		MMCINFO("Should not w/r secure area in fun %s,line,%d in start %d,end %d\n",\
			__FUNCTION__,__LINE__ ,start,start + blkcnt-1);
		return -1;
	}
	return mmc_mmc_erase(dev_num, start, blkcnt, skip_space);
}

int mmc_mmc_trim_secure(int dev_num, unsigned int start, unsigned int blkcnt)
{
	if(check_secure_area(start,blkcnt)){
		MMCINFO("Should not w/r secure area in fun %s,line,%d in start %d,end %d\n",\
			__FUNCTION__,__LINE__ ,start,start + blkcnt-1);
		return -1;
	}
	return mmc_mmc_trim(dev_num, start, blkcnt);
}

int mmc_mmc_discard_secure(int dev_num, unsigned int start, unsigned int blkcnt)
{
	if(check_secure_area(start,blkcnt)){
		MMCINFO("Should not w/r secure area in fun %s,line,%d in start %d,end %d\n",\
			__FUNCTION__,__LINE__ ,start,start + blkcnt-1);
		return -1;
	}
	return mmc_mmc_discard(dev_num, start, blkcnt);
}

int mmc_mmc_sanitize_secure(int dev_num)
{
	return mmc_mmc_sanitize(dev_num);
}
int mmc_mmc_secure_erase_secure(int dev_num, unsigned int start, unsigned int blkcnt, unsigned int *skip_space)
{
	if(check_secure_area(start,blkcnt)){
		MMCINFO("Should not w/r secure area in fun %s,line,%d in start %d,end %d\n",\
			__FUNCTION__,__LINE__ ,start,start + blkcnt-1);
		return -1;
	}
	return mmc_mmc_secure_erase(dev_num, start, blkcnt, skip_space);
}
int mmc_mmc_secure_trim_secure(int dev_num, unsigned int start, unsigned int blkcnt)
{
	if(check_secure_area(start,blkcnt)){
		MMCINFO("Should not w/r secure area in fun %s,line,%d in start %d,end %d\n",\
			__FUNCTION__,__LINE__ ,start,start + blkcnt-1);
		return -1;
	}
	return mmc_mmc_secure_trim(dev_num, start, blkcnt);
}

static ulong
mmc_bwrite_secure(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
{
	if(check_secure_area(start,blkcnt)){
		MMCINFO("Should not w/r secure area in fun %s,line,%d in start %d,end %d\n",\
			__FUNCTION__,__LINE__ ,start,start + blkcnt-1);
		return -1;
	}

	return mmc_bwrite(dev_num, start, blkcnt, src);
}


static int get_sdmmc_secure_storage_max_item(void){
	return MAX_SECURE_STORAGE_MAX_ITEM;
}


static int sdmmc_secure_storage_write(s32 dev_num,u32 item,u8 *buf , lbaint_t blkcnt)
{
	s32 ret = 0;

	if(buf == NULL){
		MMCINFO("intput buf is NULL %d\n");
		return -1;
	}

	if(item > MAX_SECURE_STORAGE_MAX_ITEM){
		MMCINFO("item exceed %d\n",MAX_SECURE_STORAGE_MAX_ITEM);
		return -1;
	}

	if(blkcnt > SDMMC_ITEM_SIZE){
		MMCINFO("block count exceed %d\n",SDMMC_ITEM_SIZE);
		return -1;
	}
	//first backups
	ret = mmc_bwrite(dev_num,SDMMC_SECURE_STORAGE_START_ADD+SDMMC_ITEM_SIZE*2*item,blkcnt,buf);
	if(ret != blkcnt){
		MMCINFO("Write first backup failed\n");
		return -1;
	}
	//second backups
	ret = mmc_bwrite(dev_num,SDMMC_SECURE_STORAGE_START_ADD+SDMMC_ITEM_SIZE*2*item+SDMMC_ITEM_SIZE,blkcnt,buf);
	if(ret != blkcnt){
		MMCINFO("Write second backup failed\n");
		return -1;
	}
	return blkcnt;
}


static int sdmmc_secure_storage_read(s32 dev_num,u32 item,u8 *buf , lbaint_t blkcnt)
{
	s32 ret = 0;
	s32 *fst_bak = (s32 *)buf;

	if(buf == NULL){
		MMCINFO("intput buf is NULL %d\n");
		ret = -1;
		goto out;

	}

	if(item > MAX_SECURE_STORAGE_MAX_ITEM){
		MMCINFO("item exceed %d\n",MAX_SECURE_STORAGE_MAX_ITEM);
		ret = -1;
		goto out;
	}

	if(blkcnt > SDMMC_ITEM_SIZE){
		MMCINFO("block count exceed %d\n",SDMMC_ITEM_SIZE);
		ret = -1;
		goto out;
	}

	//first backups
	ret = mmc_bread(dev_num,SDMMC_SECURE_STORAGE_START_ADD+SDMMC_ITEM_SIZE*2*item,blkcnt,fst_bak);
	if(ret != blkcnt){
		MMCINFO("read first backup failed in fun %s line %d\n",__FUNCTION__,__LINE__);
		ret = -1;
	}
	
out:
	return ret;
}

static int sdmmc_secure_storage_read_backup(s32 dev_num,u32 item,u8 *buf , lbaint_t blkcnt)
{
	s32 ret = 0;
	s32 *sec_bak = (s32 *)buf;

	if(buf == NULL){
		MMCINFO("intput buf is NULL %d\n");
		ret = -1;
		goto out;

	}

	if(item > MAX_SECURE_STORAGE_MAX_ITEM){
		MMCINFO("item exceed %d\n",MAX_SECURE_STORAGE_MAX_ITEM);
		ret = -1;
		goto out;
	}

	if(blkcnt > SDMMC_ITEM_SIZE){
		MMCINFO("block count exceed %d\n",SDMMC_ITEM_SIZE);
		ret = -1;
		goto out;
	}
	//second backups
	ret = mmc_bread(dev_num,SDMMC_SECURE_STORAGE_START_ADD+SDMMC_ITEM_SIZE*2*item+SDMMC_ITEM_SIZE,blkcnt,sec_bak);
	if(ret != blkcnt){
		MMCINFO("read second backup failed fun %s line %d\n",__FUNCTION__,__LINE__);
		ret = -1;
	}

out:
	return ret;	
}
#endif

int mmc_go_idle(struct mmc* mmc)
{
	struct mmc_cmd cmd;
	int err;

	udelay(1000);

	cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
	cmd.cmdarg = 0;
	cmd.resp_type = MMC_RSP_NONE;
	cmd.flags = 0;

	err = mmc_send_cmd(mmc, &cmd, NULL);

	if (err){
		MMCINFO("go idle failed\n");
		return err;
	}

	udelay(2000);

	return 0;
}

int
sd_send_op_cond(struct mmc *mmc)
{
	int timeout = 1000;
	int err;
	struct mmc_cmd cmd;

	do {
		cmd.cmdidx = MMC_CMD_APP_CMD;
		cmd.resp_type = MMC_RSP_R1;
		cmd.cmdarg = 0;
		cmd.flags = 0;

		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err){
			MMCINFO("send app cmd failed\n");
			return err;
		}

		cmd.cmdidx = SD_CMD_APP_SEND_OP_COND;
		cmd.resp_type = MMC_RSP_R3;

		/*
		 * Most cards do not answer if some reserved bits
		 * in the ocr are set. However, Some controller
		 * can set bit 7 (reserved for low voltages), but
		 * how to manage low voltages SD card is not yet
		 * specified.
		 */
		cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
			(mmc->voltages & 0xff8000);

		if (mmc->version == SD_VERSION_2)
			cmd.cmdarg |= OCR_HCS;

		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err){
			MMCINFO("send cmd41 failed\n");
			return err;
		}

		udelay(1000);
	} while ((!(cmd.response[0] & OCR_BUSY)) && timeout--);

	if (timeout < 0){
		MMCINFO("wait card init failed\n");
		return UNUSABLE_ERR;
	}

	if (mmc->version != SD_VERSION_2)
		mmc->version = SD_VERSION_1_0;

	if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
		cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
		cmd.resp_type = MMC_RSP_R3;
		cmd.cmdarg = 0;
		cmd.flags = 0;

		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err){
			MMCINFO("spi read ocr failed\n");
			return err;
		}
	}

	mmc->ocr = cmd.response[0];

	mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
	mmc->rca = 0;

	return 0;
}

int mmc_send_op_cond(struct mmc *mmc)
{
	int timeout = 10000;
	struct mmc_cmd cmd;
	int err;

	/* Some cards seem to need this */
	mmc_go_idle(mmc);

 	/* Asking to the card its capabilities */
 	cmd.cmdidx = MMC_CMD_SEND_OP_COND;
 	cmd.resp_type = MMC_RSP_R3;
 	cmd.cmdarg = 0x40ff8000;//foresee
 	cmd.flags = 0;

 	err = mmc_send_cmd(mmc, &cmd, NULL);

 	if (err){
 		MMCINFO("mmc send op cond failed\n");
 		return err;
 	}

 	udelay(1000);

	do {
		cmd.cmdidx = MMC_CMD_SEND_OP_COND;
		cmd.resp_type = MMC_RSP_R3;
		cmd.cmdarg = (mmc_host_is_spi(mmc) ? 0 :
				(mmc->voltages &
				(cmd.response[0] & OCR_VOLTAGE_MASK)) |
				(cmd.response[0] & OCR_ACCESS_MODE));

		if (mmc->host_caps & MMC_MODE_HC)
			cmd.cmdarg |= OCR_HCS;

		cmd.flags = 0;

		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err){
			MMCINFO("mmc send op cond failed\n");
			return err;
		}

		udelay(1000);
	} while (!(cmd.response[0] & OCR_BUSY) && timeout--);

	if (timeout < 0){
		MMCINFO("wait for mmc init failed\n");
		return UNUSABLE_ERR;
	}

	if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
		cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
		cmd.resp_type = MMC_RSP_R3;
		cmd.cmdarg = 0;
		cmd.flags = 0;

		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err){
			MMCINFO("spi read ocr failed\n");
			return err;
		}
	}

	mmc->version = MMC_VERSION_UNKNOWN;
	mmc->ocr = cmd.response[0];

	mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
	mmc->rca = 1;

	return 0;
}


int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)
{
	struct mmc_cmd cmd;
	struct mmc_data data;
	int err;

	/* Get the Card Status Register */
	cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = 0;
	cmd.flags = 0;

	data.dest = ext_csd;
	data.blocks = 1;
	data.blocksize = 512;
	data.flags = MMC_DATA_READ;

	err = mmc_send_cmd(mmc, &cmd, &data);
	if(err)
		MMCINFO("mmc send ext csd failed\n");

	return err;
}

/* decode ext_csd */
static int mmc_decode_ext_csd(struct mmc *mmc,
	struct mmc_ext_csd *dec_ext_csd, u8 *ext_csd)
{
	int err = 0;

	if ((!ext_csd) || !(dec_ext_csd))
		return 0;

	/* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */
	dec_ext_csd->raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE];


	dec_ext_csd->rev = ext_csd[EXT_CSD_REV];
	if (dec_ext_csd->rev > 8) {
		MMCINFO("unrecognised EXT_CSD revision %d, maybe ver5.2 or later version!\n", dec_ext_csd->rev);
		//err = -1;
		//goto out;
	}

	dec_ext_csd->raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0];
	dec_ext_csd->raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1];
	dec_ext_csd->raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2];
	dec_ext_csd->raw_sectors[3] = ext_csd[EXT_CSD_SEC_CNT + 3];
	if (dec_ext_csd->rev >= 2) {
		dec_ext_csd->sectors =
			ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
			ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
			ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
			ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
	}

	dec_ext_csd->raw_card_type = ext_csd[EXT_CSD_CARD_TYPE];

	dec_ext_csd->raw_erase_timeout_mult =
		ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT];
	dec_ext_csd->raw_hc_erase_grp_size =
		ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
	if (dec_ext_csd->rev >= 3) {
		dec_ext_csd->erase_group_def =
			ext_csd[EXT_CSD_ERASE_GROUP_DEF];
		dec_ext_csd->hc_erase_timeout = 300 *
			ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT];
		dec_ext_csd->hc_erase_size =
			ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10;
	}

	dec_ext_csd->raw_hc_erase_gap_size =
		ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
	dec_ext_csd->raw_sec_trim_mult =
		ext_csd[EXT_CSD_SEC_TRIM_MULT];
	dec_ext_csd->raw_sec_erase_mult =
		ext_csd[EXT_CSD_SEC_ERASE_MULT];
	dec_ext_csd->raw_sec_feature_support =
		ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
	dec_ext_csd->raw_trim_mult =
		ext_csd[EXT_CSD_TRIM_MULT];

	if (dec_ext_csd->rev >= 4) {
		dec_ext_csd->sec_trim_mult =
			ext_csd[EXT_CSD_SEC_TRIM_MULT];
		dec_ext_csd->sec_erase_mult =
			ext_csd[EXT_CSD_SEC_ERASE_MULT];
		dec_ext_csd->sec_feature_support =
			ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
		dec_ext_csd->trim_timeout = 300 *
			ext_csd[EXT_CSD_TRIM_MULT];
	}

	dec_ext_csd->raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT];

	/* eMMC v4.5 or later */
	if (dec_ext_csd->rev >= 6) {
		dec_ext_csd->generic_cmd6_time = 10 *
			ext_csd[EXT_CSD_GENERIC_CMD6_TIME];
		dec_ext_csd->power_off_longtime = 10 *
			ext_csd[EXT_CSD_POWER_OFF_LONG_TIME];

	} else {
		dec_ext_csd->data_sector_size = 512;
	}

//out:
	return err;
}

int mmc_do_switch(struct mmc *mmc, u8 set, u8 index, u8 value, u32 timeout)
{
	struct mmc_cmd cmd;
	int ret;

	cmd.cmdidx = MMC_CMD_SWITCH;
	cmd.resp_type = MMC_RSP_R1b;
	cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
				 (index << 16) |
				 (value << 8);
	cmd.flags = 0;

	ret = mmc_send_cmd(mmc, &cmd, NULL);
	if(ret){
		MMCINFO("mmc switch failed\n");
	}

	ret = mmc_update_phase(mmc);
	if (ret)
	{
		MMCINFO("update clock failed after send switch cmd\n");
		return ret;
	}

	/* Waiting for the ready status */
	mmc_send_status(mmc, timeout);

	return ret;
}

int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
{
	int timeout = 1000;
	return mmc_do_switch(mmc, set, index, value, timeout);
}

int mmc_change_freq(struct mmc *mmc)
{
	char ext_csd[512];
	char cardtype;
	int err;
	int retry = 5;

	mmc->card_caps = 0;

	if (mmc_host_is_spi(mmc))
		return 0;

	/* Only version 4 supports high-speed */
	if (mmc->version < MMC_VERSION_4)
		return 0;
	//here we assume eMMC support 8 bit
	mmc->card_caps |= MMC_MODE_4BIT|MMC_MODE_8BIT;

	err = mmc_send_ext_csd(mmc, ext_csd);

	if (err){
		MMCINFO("mmc get ext csd failed\n");
		return err;
	}

	cardtype = ext_csd[196] & 0xf;

	//retry for Toshiba emmc;for the first time Toshiba emmc change to HS
	//it will return response crc err,so retry
	do{
		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
		if(!err){
			break;
		}
		MMCINFO("retry mmc switch(cmd6)\n");
	}while(retry--);

	if (err){
		MMCINFO("mmc change to hs failed\n");
		return err;
	}

	err = mmc_update_phase(mmc);
	if (err)
	{
		MMCINFO("update clock failed\n");
		return err;
	}

	/* Now check to see that it worked */
	err = mmc_send_ext_csd(mmc, ext_csd);

	if (err){
		MMCINFO("send ext csd faild\n");
		return err;
	}

	/* No high-speed support */
	if (!ext_csd[185])
		return 0;

	/* High Speed is set, there are two types: 52MHz and 26MHz */
	if (cardtype & MMC_HS_52MHZ)
		mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
	else
		mmc->card_caps |= MMC_MODE_HS;

	if (cardtype & MMC_DDR_52MHZ){
		mmc->card_caps |= MMC_MODE_DDR_52MHz;
		MMCDBG("get ddr OK!\n");
	}else{
		MMCINFO("get ddr fail!\n");
	}


	return 0;
}


int mmc_switch_boot_bus_cond(int dev_num, u32 boot_mode, u32 rst_bus_cond, u32 bus_width)
{
	char ext_csd[512]={0};
	unsigned char boot_bus_cond = 0;
	int ret = 0;
	struct mmc *mmc = find_mmc_device(dev_num);
	if (!mmc){
		MMCINFO("can not find mmc device\n");
		return -1;
	}


	boot_bus_cond = (mmc->boot_bus_cond &
			  	(~MMC_SWITCH_BOOT_MODE_MASK) & (~MMC_SWITCH_BOOT_RST_BUS_COND_MASK) & (~MMC_SWITCH_BOOT_BUS_WIDTH_MASK))
			  | ((boot_mode << 3) & MMC_SWITCH_BOOT_MODE_MASK)
			  | ((rst_bus_cond << 2) & MMC_SWITCH_BOOT_RST_BUS_COND_MASK)
			  | ((bus_width) & MMC_SWITCH_BOOT_BUS_WIDTH_MASK);

	ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_COND,boot_bus_cond);
	if(ret){
		MMCINFO("switch bus cond failed\n");
		return -1;
	}
	ret = mmc_send_ext_csd(mmc, ext_csd);
	if(ret){
		MMCINFO("send ext csd failed\n");
		return -1;
	}
	MMCDBG("boot bus cond:0x%x\n",ext_csd[EXT_CSD_BOOT_BUS_COND]);
	if(boot_bus_cond!=ext_csd[EXT_CSD_BOOT_BUS_COND])	{
		MMCINFO("Set boot bus cond failed,now bus con is 0x%x\n",ext_csd[EXT_CSD_BOOT_BUS_COND]);
		return -1;
	}
	mmc->boot_bus_cond = boot_bus_cond;
	return ret;
}

int mmc_switch_boot_part(int dev_num, u32 boot_ack, u32 boot_part)
{
	char ext_csd[512]={0};
	unsigned char part_config = 0;
	int ret = 0;
	struct mmc *mmc = find_mmc_device(dev_num);
	if (!mmc){
		MMCINFO("can not find mmc device\n");
		return -1;
	}


	part_config = (mmc->part_config & (~MMC_SWITCH_PART_BOOT_PART_MASK) & (~MMC_SWITCH_PART_BOOT_ACK_MASK))
			  				| ((boot_part << 3) & MMC_SWITCH_PART_BOOT_PART_MASK) | (boot_ack << 6);
	ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,part_config);

	if(ret){
		MMCINFO("switch boot partd failed\n");
		return -1;
	}
	ret = mmc_send_ext_csd(mmc, ext_csd);
	if(ret){
		MMCINFO("send ext csd failed\n");
		return -1;
	}

	MMCDBG("part conf:0x%x\n",ext_csd[EXT_CSD_PART_CONF]);
	if(part_config!=ext_csd[EXT_CSD_PART_CONF])	{
		MMCINFO("switch boot part failed,now part conf is 0x%x\n",ext_csd[EXT_CSD_PART_CONF]);
		return -1;
	}
	mmc->part_config = part_config;
	return ret;
}



int mmc_switch_part(int dev_num, unsigned int part_num)
{
	char ext_csd[512]={0};
	unsigned char part_config = 0;
	int ret = 0;
	struct mmc *mmc = find_mmc_device(dev_num);

	MMCDBG("Try to switch part \n");
	if (!mmc){
		MMCINFO("can not find mmc device\n");
		return -1;
	}


	part_config = (mmc->part_config & ~PART_ACCESS_MASK)
			  					| (part_num & PART_ACCESS_MASK);
	ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,part_config);
	if(ret){
		MMCINFO("mmc switch part failed\n");
		return -1;
	}
	ret = mmc_send_ext_csd(mmc, ext_csd);
	if(ret){
		MMCINFO("send ext csd failed\n");
		return -1;
	}
	MMCDBG("part conf:0x%x\n",ext_csd[EXT_CSD_PART_CONF]);
	if(part_config!=ext_csd[EXT_CSD_PART_CONF])	{
		MMCINFO("switch boot part failed,now bus con is 0x%x\n",ext_csd[EXT_CSD_PART_CONF]);
		return -1;
	}
	mmc->part_config = part_config;

	MMCDBG("switch part succeed\n");
	return ret;

}

int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
{
	struct mmc_cmd cmd;
	struct mmc_data data;

	/* Switch the frequency */
	cmd.cmdidx = SD_CMD_SWITCH_FUNC;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = (mode << 31) | 0xffffff;
	cmd.cmdarg &= ~(0xf << (group * 4));
	cmd.cmdarg |= value << (group * 4);
	cmd.flags = 0;

	data.dest = (char *)resp;
	data.blocksize = 64;
	data.blocks = 1;
	data.flags = MMC_DATA_READ;

	return mmc_send_cmd(mmc, &cmd, &data);
}


int sd_change_freq(struct mmc *mmc)
{
	int err;
	struct mmc_cmd cmd;
	uint scr[2];
	uint switch_status[16];
	struct mmc_data data;
	int timeout;

	mmc->card_caps = 0;

	if (mmc_host_is_spi(mmc))
		return 0;

	/* Read the SCR to find out if this card supports higher speeds */
	cmd.cmdidx = MMC_CMD_APP_CMD;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = mmc->rca << 16;
	cmd.flags = 0;

	err = mmc_send_cmd(mmc, &cmd, NULL);

	if (err){
		MMCINFO("Send app cmd failed\n");
		return err;
	}

	cmd.cmdidx = SD_CMD_APP_SEND_SCR;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = 0;
	cmd.flags = 0;

	timeout = 3;

retry_scr:
	data.dest = (char *)&scr;
	data.blocksize = 8;
	data.blocks = 1;
	data.flags = MMC_DATA_READ;

	err = mmc_send_cmd(mmc, &cmd, &data);

	if (err) {
		if (timeout--)
			goto retry_scr;

		MMCINFO("Send scr failed\n");
		return err;
	}

	mmc->scr[0] = __be32_to_cpu(scr[0]);
	mmc->scr[1] = __be32_to_cpu(scr[1]);

	switch ((mmc->scr[0] >> 24) & 0xf) {
		case 0:
			mmc->version = SD_VERSION_1_0;
			break;
		case 1:
			mmc->version = SD_VERSION_1_10;
			break;
		case 2:
			mmc->version = SD_VERSION_2;
			break;
		default:
			mmc->version = SD_VERSION_1_0;
			break;
	}

	if (mmc->scr[0] & SD_DATA_4BIT)
		mmc->card_caps |= MMC_MODE_4BIT;

	/* Version 1.0 doesn't support switching */
	if (mmc->version == SD_VERSION_1_0)
		return 0;

	timeout = 4;
	while (timeout--) {
		err = sd_switch(mmc, SD_SWITCH_CHECK, 0, 1,
				(u8 *)&switch_status);

		if (err){
			MMCINFO("Check high speed status faild\n");
			return err;
		}

		/* The high-speed function is busy.  Try again */
		if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY))
			break;
	}

	/* If high-speed isn't supported, we return */
	if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
		return 0;

	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)&switch_status);

	if (err){
		MMCINFO("switch to high speed failed\n");
		return err;
	}

	err = mmc_update_phase(mmc);
	if (err)
	{
		MMCINFO("update clock failed\n");
		return err;
	}

	if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000)
		mmc->card_caps |= MMC_MODE_HS;

	return 0;
}

/* frequency bases */
/* divided by 10 to be nice to platforms without floating point */
static const int fbase[] = {
	10000,
	100000,
	1000000,
	10000000,
};

/* Multiplier values for TRAN_SPEED.  Multiplied by 10 to be nice
 * to platforms without floating point.
 */
static const int multipliers[] = {
	0,	/* reserved */
	10,
	12,
	13,
	15,
	20,
	25,
	30,
	35,
	40,
	45,
	50,
	55,
	60,
	70,
	80,
};

void mmc_set_ios(struct mmc *mmc)
{
	mmc->set_ios(mmc);
}



void mmc_set_clock(struct mmc *mmc, uint clock)
{
	if (clock > mmc->f_max)
		clock = mmc->f_max;

	if (clock < mmc->f_min)
		clock = mmc->f_min;

	mmc->clock = clock;

	mmc_set_ios(mmc);
}

void mmc_set_bus_width(struct mmc *mmc, uint width)
{
	mmc->bus_width = width;

	mmc_set_ios(mmc);
}

int mmc_startup(struct mmc *mmc)
{
	int err;
	uint mult, freq;
	u64 cmult, csize, capacity;
	struct mmc_cmd cmd;
	char ext_csd[512];
	int timeout = 1000;

#ifdef CONFIG_MMC_SPI_CRC_ON
	if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
		cmd.cmdidx = MMC_CMD_SPI_CRC_ON_OFF;
		cmd.resp_type = MMC_RSP_R1;
		cmd.cmdarg = 1;
		cmd.flags = 0;
		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err){
			MMCINFO("Spi crc on off failed\n");
			return err;
		}
	}
#endif

	/* Put the Card in Identify Mode */
	cmd.cmdidx = mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID :
		MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */
	cmd.resp_type = MMC_RSP_R2;
	cmd.cmdarg = 0;
	cmd.flags = 0;

	err = mmc_send_cmd(mmc, &cmd, NULL);

	if (err){
		MMCINFO("Put the Card in Identify Mode failed\n");
		return err;
	}

	memcpy(mmc->cid, cmd.response, 16);

	/*
	 * For MMC cards, set the Relative Address.
	 * For SD cards, get the Relatvie Address.
	 * This also puts the cards into Standby State
	 */
	if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
		cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
		cmd.cmdarg = mmc->rca << 16;
		cmd.resp_type = MMC_RSP_R6;
		cmd.flags = 0;

		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err){
			MMCINFO("send rca failed\n");
			return err;
		}

		if (IS_SD(mmc))
			mmc->rca = (cmd.response[0] >> 16) & 0xffff;
	}

	/* Get the Card-Specific Data */
	cmd.cmdidx = MMC_CMD_SEND_CSD;
	cmd.resp_type = MMC_RSP_R2;
	cmd.cmdarg = mmc->rca << 16;
	cmd.flags = 0;

	err = mmc_send_cmd(mmc, &cmd, NULL);

	/* Waiting for the ready status */
	mmc_send_status(mmc, timeout);

	if (err){
		MMCINFO("get csd failed\n");
		return err;
	}

	mmc->csd[0] = cmd.response[0];
	mmc->csd[1] = cmd.response[1];
	mmc->csd[2] = cmd.response[2];
	mmc->csd[3] = cmd.response[3];

	if (mmc->version == MMC_VERSION_UNKNOWN) {
		int version = (cmd.response[0] >> 26) & 0xf;

		switch (version) {
			case 0:
				mmc->version = MMC_VERSION_1_2;
				break;
			case 1:
				mmc->version = MMC_VERSION_1_4;
				break;
			case 2:
				mmc->version = MMC_VERSION_2_2;
				break;
			case 3:
				mmc->version = MMC_VERSION_3;
				break;
			case 4:
				mmc->version = MMC_VERSION_4;
				break;
			default:
				mmc->version = MMC_VERSION_1_2;
				break;
		}
	}

	/* divide frequency by 10, since the mults are 10x bigger */
	freq = fbase[(cmd.response[0] & 0x7)];
	mult = multipliers[((cmd.response[0] >> 3) & 0xf)];

	mmc->tran_speed = freq * mult;

	mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);

	if (IS_SD(mmc))
		mmc->write_bl_len = mmc->read_bl_len;
	else
		mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);

	if (mmc->high_capacity) {
		csize = (mmc->csd[1] & 0x3f) << 16
			| (mmc->csd[2] & 0xffff0000) >> 16;
		cmult = 8;
	} else {
		csize = (mmc->csd[1] & 0x3ff) << 2
			| (mmc->csd[2] & 0xc0000000) >> 30;
		cmult = (mmc->csd[2] & 0x00038000) >> 15;
	}

	mmc->capacity = (csize + 1) << (cmult + 2);
	mmc->capacity *= mmc->read_bl_len;

	if (mmc->read_bl_len > 512)
		mmc->read_bl_len = 512;

	if (mmc->write_bl_len > 512)
		mmc->write_bl_len = 512;

	/* Select the card, and put it into Transfer Mode */
	if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
		cmd.cmdidx = MMC_CMD_SELECT_CARD;
		cmd.resp_type = MMC_RSP_R1b;
		cmd.cmdarg = mmc->rca << 16;
		cmd.flags = 0;
		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err){
			MMCINFO("Select the card failed\n");
			return err;
		}
	}

	/*
	 * For SD, its erase group is always one sector
	 */
	mmc->erase_grp_size = 1;
	mmc->part_config = MMCPART_NOAVAILABLE;
	if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {
		/* check  ext_csd version and capacity */
		err = mmc_send_ext_csd(mmc, ext_csd);

		if(!err){
				/* update mmc version */
			switch (ext_csd[192]) {
				case 0:
					mmc->version = MMC_VERSION_4;
					break;
				case 1:
					mmc->version = MMC_VERSION_4_1;
					break;
				case 2:
					mmc->version = MMC_VERSION_4_2;
					break;
				case 3:
					mmc->version = MMC_VERSION_4_3;
					break;
				case 5:
					mmc->version = MMC_VERSION_4_41;
					break;
				case 6:
					mmc->version = MMC_VERSION_4_5;
					break;
				case 7:
					mmc->version = MMC_VERSION_5_0;
					break;
				case 8:
					mmc->version = MMC_VERSION_5_1;
					break;
				default:
					if (ext_csd[EXT_CSD_REV] > 8)
						mmc->version = MMC_VERSION_NEW_VER;
					else
						MMCINFO("Invalid ext_csd revision %d\n", ext_csd[192]);
					break;
			}
		}


		if (!err & (ext_csd[192] >= 2)) {
			/*
			 * According to the JEDEC Standard, the value of
			 * ext_csd's capacity is valid if the value is more
			 * than 2GB
			 */
			capacity = ext_csd[212] << 0 | ext_csd[213] << 8 |
				   ext_csd[214] << 16 | ext_csd[215] << 24;
			capacity *= 512;
			if ((capacity >> 20) > 2 * 1024)
				mmc->capacity = capacity;
		}

		/*
		  * Get timeout value
		  */
		mmc_mmc_update_timeout(mmc);

		/*
		 * Check whether GROUP_DEF is set, if yes, read out
		 * group size from ext_csd directly, or calculate
		 * the group size from the csd value.
		 *
		 *  WJQ, 20141022
		 *  take write block as the unit of erase group
		 */
		{
			int erase_gsz, erase_gmul;
			int def_erase_grp_size, hc_erase_gpr_size;
			int hc_erase_timeout;

			erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
			erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
			def_erase_grp_size = (erase_gsz + 1) * (erase_gmul + 1);

			hc_erase_gpr_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 512 * 1024;
			hc_erase_gpr_size = hc_erase_gpr_size / mmc->write_bl_len;

			hc_erase_timeout = 300 * ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT];

			if (ext_csd[EXT_CSD_ERASE_GROUP_DEF] && hc_erase_gpr_size && hc_erase_timeout)
				mmc->erase_grp_size = hc_erase_gpr_size;
			else
				mmc->erase_grp_size = def_erase_grp_size;
		}

		mmc->secure_feature = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
		mmc->secure_removal_type = ext_csd[EXT_CSD_SECURE_REMOAL_TYPE];

		/* store the partition info of emmc */
		if (ext_csd[226])//ext_csd[160] & PART_SUPPORT
		{
		  	mmc->boot_support = 1;//lwj
			mmc->part_support = ext_csd[160];
			mmc->part_config = ext_csd[179];
			mmc->boot1_lba	= 128000*ext_csd[226]/512;
			mmc->boot2_lba	= 128000*ext_csd[226]/512;
			mmc->boot_bus_cond = ext_csd[177];

			MMCDBG("PART_SUPPORT mmc->boot1_lba = %d\n",mmc->boot1_lba);
		}
		else
		{
			MMCDBG("not PART_SUPPORT ext_csd[226] = %d\n",ext_csd[226]);
		}
	}


	mmc_set_clock(mmc,25000000);

	if (IS_SD(mmc))
		err = sd_change_freq(mmc);
	else
		err = mmc_change_freq(mmc);

	if (err){
		MMCINFO("Change speed mode failed\n");
		return err;
	}
	
	/* for re-update sample phase */
	err = mmc_update_phase(mmc);
	if (err)
	{
		MMCINFO("update clock failed\n");
		return err;
	}
	
	/* Restrict card's capabilities by what the host can do */
	mmc->card_caps &= mmc->host_caps;

	if (IS_SD(mmc)) {
		if (mmc->card_caps & MMC_MODE_4BIT) {
			cmd.cmdidx = MMC_CMD_APP_CMD;
			cmd.resp_type = MMC_RSP_R1;
			cmd.cmdarg = mmc->rca << 16;
			cmd.flags = 0;

			err = mmc_send_cmd(mmc, &cmd, NULL);
			if (err){
				MMCINFO("send app cmd failed\n");
				return err;
			}

			cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
			cmd.resp_type = MMC_RSP_R1;
			cmd.cmdarg = 2;
			cmd.flags = 0;
			err = mmc_send_cmd(mmc, &cmd, NULL);
			if (err){
				MMCINFO("sd set bus width failed\n");
				return err;
			}

			mmc_set_bus_width(mmc, 4);
		}

		if (mmc->card_caps & MMC_MODE_HS)
			mmc_set_clock(mmc, 50000000);
		else
			mmc_set_clock(mmc, 25000000);
	} else {
		if (mmc->card_caps & MMC_MODE_8BIT) {

			if( (mmc->card_caps & MMC_MODE_DDR_52MHz) ){
				MMCINFO("ddr8 \n");
				/* Set the card to use 8 bit ddr*/
				err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
						EXT_CSD_BUS_WIDTH,
						EXT_CSD_BUS_DDR_8);
				if (err){
					MMCINFO("mmc switch bus width failed\n");
					return err;
				}
				mmc_set_bus_width(mmc, 8);
			}else{
				/* Set the card to use 8 bit*/
				err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
						EXT_CSD_BUS_WIDTH,
						EXT_CSD_BUS_WIDTH_8);

				if (err){
					MMCINFO("mmc switch bus width8 failed\n");
					return err;
				}
				mmc_set_bus_width(mmc, 8);
			}

		}else if (mmc->card_caps & MMC_MODE_4BIT) {
			if ( (mmc->card_caps & MMC_MODE_DDR_52MHz) ){
				MMCINFO("ddr4 \n");
				/* Set the card to use 4 bit ddr*/
				err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
						EXT_CSD_BUS_WIDTH,
						EXT_CSD_BUS_DDR_4);
				if (err){
					MMCINFO("mmc switch bus width failed\n");
					return err;
				}
				mmc_set_bus_width(mmc, 4);
			}else{
				/* Set the card to use 4 bit*/
				err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
						EXT_CSD_BUS_WIDTH,
						EXT_CSD_BUS_WIDTH_4);
				if (err){
					MMCINFO("mmc switch bus width failed\n");
					return err;
				}
				mmc_set_bus_width(mmc, 4);
			}
		}

		if( (mmc->card_caps & MMC_MODE_DDR_52MHz) ){
			mmc->io_mode = MMC_MODE_DDR_52MHz;
			MMCDBG("mmc mmc->io_mode = %x\n",mmc->io_mode);
			mmc_set_clock(mmc, 50000000);
		}else if (mmc->card_caps & MMC_MODE_HS) {
			if (mmc->card_caps & MMC_MODE_HS_52MHz)
				mmc_set_clock(mmc, 52000000);
			else
				mmc_set_clock(mmc, 26000000);
		} else{
				mmc_set_clock(mmc, 20000000);
		}
	}

	/* fill in device description */
	mmc->block_dev.lun = 0;
	mmc->block_dev.type = 0;
	mmc->block_dev.blksz = mmc->read_bl_len;
	mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
	if (IS_SD(mmc)){
		sprintf(mmc->block_dev.vendor, "MID %06x PSN %08x",
			mmc->cid[0] >> 24, (mmc->cid[2] << 8) | (mmc->cid[3] >> 24));
		sprintf(mmc->block_dev.product, "PNM %c%c%c%c%c", mmc->cid[0] & 0xff,
			(mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
			(mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
		sprintf(mmc->block_dev.revision, "PRV %d.%d", mmc->cid[2] >> 28,
			(mmc->cid[2] >> 24) & 0xf);
	} else {
		sprintf(mmc->block_dev.vendor, "MID %06x PSN %04x%04x",
			mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
			(mmc->cid[3] >> 16) & 0xffff);
		sprintf(mmc->block_dev.product, "PNM %c%c%c%c%c%c", mmc->cid[0] & 0xff,
			(mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
			(mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff,
			(mmc->cid[2] >> 24) & 0xff);
		sprintf(mmc->block_dev.revision, "PRV %d.%d", (mmc->cid[2] >> 20) & 0xf,
			(mmc->cid[2] >> 16) & 0xf);
	}

	MMCDBG("%s\n", mmc->block_dev.vendor);
	MMCDBG("%s -- 0x%02x-%02x-%02x-%02x-%02x-%02x\n", mmc->block_dev.product,
			mmc->cid[0] & 0xff, (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
			(mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
	MMCDBG("%s\n", mmc->block_dev.revision);

	if (IS_SD(mmc)){
		MMCDBG("MDT m-%d y-%d\n", ((mmc->cid[3] >> 8) & 0xF), (((mmc->cid[3] >> 12) & 0xFF) + 2000));
	} else {
		if (ext_csd[192] > 4) {
			MMCDBG("MDT m-%d y-%d\n", ((mmc->cid[3] >> 12) & 0xF),
				(((mmc->cid[3] >> 8) & 0xF) < 13) ? (((mmc->cid[3] >> 8) & 0xF) + 2013) : (((mmc->cid[3] >> 8) & 0xF) + 1997));
		} else {
			MMCDBG("MDT m-%d y-%d\n", ((mmc->cid[3] >> 12) & 0xF), (((mmc->cid[3] >> 8) & 0xF) + 1997));
		}
	}

    MMCINFO("CID 0x%x 0x%x 0x%x 0x%x\n",mmc->cid[0],mmc->cid[1],mmc->cid[2],mmc->cid[3]);

    /*printf("---------------ext_csd[192] = %d--------------\n", ext_csd[192]);*/
	if(!IS_SD(mmc)){
		switch(mmc->version)
		{
			case MMC_VERSION_1_2:
				MMCINFO("MMC ver 1.2\n");
				break;
			case MMC_VERSION_1_4:
				MMCINFO("MMC ver 1.4\n");
				break;
			case MMC_VERSION_2_2:
				MMCINFO("MMC ver 2.2\n");
				break;
			case MMC_VERSION_3:
				MMCINFO("MMC ver 3.0\n");
				break;
			case MMC_VERSION_4:
				MMCINFO("MMC ver 4.0\n");
				break;
			case MMC_VERSION_4_1:
				MMCINFO("MMC ver 4.1\n");
				break;
			case MMC_VERSION_4_2:
				MMCINFO("MMC ver 4.2\n");
				break;
			case MMC_VERSION_4_3:
				MMCINFO("MMC ver 4.3\n");
				break;
			case MMC_VERSION_4_41:
				MMCINFO("MMC ver 4.41\n");
				break;
			case MMC_VERSION_4_5:
				MMCINFO("MMC ver 4.5\n");
				break;
			case MMC_VERSION_5_0:
				MMCINFO("MMC ver 5.0\n");
				break;
			case MMC_VERSION_5_1:
				MMCINFO("MMC v5.1\n");
				break;
			case MMC_VERSION_NEW_VER:
				MMCINFO("MMC v5.2 or later version\n");
				break;
			default:
				MMCINFO("Unknow MMC ver\n");
				break;
		}
	}

	mmc->clock_after_init = mmc->clock;//back up clock after mmc init

	MMCINFO("mmc clk %d\n", mmc->clock);
	//MMCINFO("---mmc bus_width %d---\n", mmc->bus_width);
	MMCINFO("SD/MMC Card: %dbit, capacity: %ldMB\n",(mmc->card_caps & MMC_MODE_8BIT)?8:(mmc->card_caps & MMC_MODE_4BIT ? 4 : 1), mmc->block_dev.lba>>11);
	MMCINFO("boot0 capacity: %dKB,boot1 capacity: %dKB\n"
						,mmc->boot1_lba*512/1024,mmc->boot2_lba*512/1024);
	MMCINFO("***SD/MMC %d init OK!!!***\n",mmc->control_num);
	//init_part(&mmc->block_dev);

	return 0;
}

int mmc_send_if_cond(struct mmc *mmc)
{
	struct mmc_cmd cmd;
	int err;

	cmd.cmdidx = SD_CMD_SEND_IF_COND;
	/* We set the bit if the host supports voltages between 2.7 and 3.6 V */
	cmd.cmdarg = ((mmc->voltages & 0xff8000) != 0) << 8 | 0xaa;
	cmd.resp_type = MMC_RSP_R7;
	cmd.flags = 0;

	err = mmc_send_cmd(mmc, &cmd, NULL);

	if (err){
		MMCINFO("mmc send if cond failed\n");
		return err;
	}

	if ((cmd.response[0] & 0xff) != 0xaa)
		return UNUSABLE_ERR;
	else
		mmc->version = SD_VERSION_2;

	return 0;
}

int mmc_register(struct mmc *mmc)
{
	/* Setup the universal parts of the block interface just once */
	mmc->block_dev.if_type = IF_TYPE_MMC;
	//mmc->block_dev.dev = cur_dev_num++;
	mmc->block_dev.dev = mmc->control_num;
	mmc->block_dev.removable = 1;
//#if 0
#ifndef CONFIG_SUNXI_SECURE_STORAGE
	mmc->block_dev.block_read 	= mmc_bread;
	mmc->block_dev.block_write 	= mmc_bwrite;
	mmc->block_dev.block_erase 	= mmc_berase;
	mmc->block_dev.block_secure_wipe = mmc_secure_wipe;
	mmc->block_dev.block_read_mass_pro  = mmc_bread_mass_pro;
	mmc->block_dev.block_write_mass_pro = mmc_bwrite_mass_pro;
	//mmc->block_dev.block_erase_mass_pro = mmc_berase_mass_pro;
	mmc->block_dev.block_read_secure 	= NULL;
	mmc->block_dev.block_write_secure	= NULL;
	mmc->block_dev.block_get_item_secure= NULL;

	mmc->block_dev.block_mmc_erase = mmc_mmc_erase;
	mmc->block_dev.block_mmc_trim = mmc_mmc_trim;
	mmc->block_dev.block_mmc_discard = mmc_mmc_discard;
	mmc->block_dev.block_mmc_sanitize = mmc_mmc_sanitize;
	mmc->block_dev.block_mmc_secure_erase = mmc_mmc_secure_erase;
	mmc->block_dev.block_mmc_secure_trim = mmc_mmc_secure_trim;
#else
	mmc->block_dev.block_read 	= mmc_bread_secure;
	mmc->block_dev.block_write 	= mmc_bwrite_secure;
	mmc->block_dev.block_erase 	= mmc_berase_secure;
	mmc->block_dev.block_secure_wipe    = mmc_secure_wipe_secure;
	mmc->block_dev.block_read_mass_pro  = mmc_bread_mass_pro_secure;
	mmc->block_dev.block_write_mass_pro = mmc_bwrite_mass_pro_secure;
	mmc->block_dev.block_read_secure 	= sdmmc_secure_storage_read;
	mmc->block_dev.block_read_secure_backup 	= sdmmc_secure_storage_read_backup;
	mmc->block_dev.block_write_secure	= sdmmc_secure_storage_write;
	mmc->block_dev.block_get_item_secure= get_sdmmc_secure_storage_max_item;

	mmc->block_dev.block_mmc_erase = mmc_mmc_erase_secure;
	mmc->block_dev.block_mmc_trim = mmc_mmc_trim_secure;
	mmc->block_dev.block_mmc_discard = mmc_mmc_discard_secure;
	mmc->block_dev.block_mmc_sanitize = mmc_mmc_sanitize_secure;
	mmc->block_dev.block_mmc_secure_erase = mmc_mmc_secure_erase_secure;
	mmc->block_dev.block_mmc_secure_trim = mmc_mmc_secure_trim_secure;
#endif

	if (!mmc->b_max)
		mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;

	INIT_LIST_HEAD (&mmc->link);

	list_add_tail (&mmc->link, &mmc_devices);

	return 0;
}

int mmc_unregister(int sdc_no)
{
	return 0;
}
#ifdef CONFIG_PARTITIONS
block_dev_desc_t *mmc_get_dev(int dev)
{
	struct mmc *mmc = find_mmc_device(dev);

	return mmc ? &mmc->block_dev : NULL;
}
#endif

/*
int sunxi_need_retry(struct mmc *mmc)
{
	if(mmc->decide_retry && mmc->update_sdly){
		uint sdly = 0;
		int ret = 0;
		ret = mmc->decide_retry(mmc,&sdly,0);
		if(ret){
			MMCINFO("need retry next dly %d,clk %d\n",sdly,mmc->clock);
			mmc->update_sdly(mmc,sdly);
			return 1;
		}
	}
	return 0;
}
*/
int sunxi_need_rty(struct mmc *mmc)
{
	if(mmc->decide_retry ){
		int ret = 0;
		u32 err_no = 0;
		err_no = mmc->get_detail_errno(mmc);
		ret = mmc->decide_retry(mmc,err_no,0);
		if(!ret){
			MMCINFO("need retry next clk %d\n",mmc->clock);
			return 0;
		}
	}
	return -1;
}





static const char tuning_blk_4b[TUNING_LEN*512] = {
	/*hs200/uhs*/
	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
	0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
	0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
	0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
	0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
	0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
	0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
	0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,

	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
	0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
	0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
	0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
	0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
	0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
	0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
	0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,

	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
	0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
	0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
	0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
	0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
	0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
	0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
	0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,

	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
	0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
	0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
	0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
	0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
	0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
	0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
	0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,

	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
	0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
	0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
	0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
	0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
	0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
	0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
	0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,

	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
	0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
	0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
	0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
	0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
	0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
	0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
	0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,

	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
	0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
	0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
	0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
	0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
	0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
	0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
	0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,

	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
	0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
	0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
	0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
	0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
	0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
	0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
	0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,

	/*0xf*/
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,

	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,

	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,

	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,

	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,

	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,

	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,

	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
	/*0x1e*/
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,

	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,

	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,

	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,

	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,

	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,

	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,

	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
	0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,

	/*0x5a*/
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,

	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,

	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,

	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,

	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,

	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,

	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,

	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
	0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,

	/*wifi*/
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
	/*0xf1*/
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,

	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,

	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,

	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,

	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,

	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,

	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,

	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
	0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,


	/*0xd2(change form 0xe1/0x1e)*/
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,

	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,

	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,

	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,

	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,

	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,

	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,

	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,

	/*0xb4(change form 0xe1/0x1e)*/
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,

	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,

	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,

	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,

	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,

	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,

	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,

	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,

	/*0x78(change form 0xe1/0x1e)*/
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,

	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,

	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,

	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,

	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,

	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,

	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,

	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,

	/*rand*/
	0xe4, 0x4f, 0x76, 0xbb, 0xf0, 0xb7, 0xe0, 0xdb,
	0xb9, 0x1f, 0x9f, 0xfb, 0x7e, 0x9b, 0x03, 0x7d,
	0x2e, 0x32, 0x8f, 0x29, 0x7a, 0x9b, 0xab, 0x16,
	0x2f, 0x44, 0x99, 0xce, 0xc3, 0x99, 0xaa, 0xad,
	0x2d, 0x82, 0xb2, 0x8a, 0xfa, 0x2d, 0xb9, 0x9a,
	0x9e, 0x0f, 0xf3, 0x90, 0x08, 0x25, 0xf3, 0x09,
	0x79, 0x80, 0x1b, 0x28, 0x95, 0x00, 0x57, 0x7d,
	0xbb, 0x60, 0x0b, 0x2c, 0x92, 0x72, 0x49, 0x4b,
	0xe4, 0xac, 0x48, 0x8b, 0xb0, 0xe4, 0x11, 0x1b,
	0x7a, 0x58, 0x7c, 0xc9, 0xe6, 0xf1, 0x5b, 0x6b,
	0x85, 0xc9, 0xf5, 0x7d, 0xef, 0xea, 0xb6, 0x0b,
	0x12, 0x59, 0x24, 0xd2, 0xc9, 0x53, 0x15, 0xa2,
	0xb1, 0xd6, 0x1f, 0x06, 0x38, 0x63, 0x51, 0x27,
	0xf6, 0x03, 0x20, 0xee, 0x41, 0x88, 0xa4, 0x69,
	0xfb, 0x15, 0x05, 0x70, 0xaf, 0xe0, 0x30, 0x88,
	0xdc, 0x37, 0xce, 0x07, 0x91, 0xc1, 0x76, 0x79,
	0x3a, 0x07, 0x21, 0x43, 0xba, 0x32, 0xdf, 0x86,
	0xba, 0x16, 0xc9, 0x46, 0x40, 0x70, 0x37, 0xcc,
	0x83, 0x6c, 0x33, 0x48, 0xfe, 0x6b, 0x2d, 0xbb,
	0xc3, 0x02, 0xf0, 0x14, 0x12, 0x46, 0xd4, 0x99,
	0x2a, 0x47, 0x35, 0x89, 0x5f, 0xda, 0x25, 0x00,
	0x6d, 0x9c, 0x5e, 0x1a, 0x0c, 0x33, 0x7a, 0x5b,
	0xc4, 0xd7, 0x67, 0x4f, 0x03, 0x12, 0x15, 0x6d,
	0x6d, 0xc3, 0x71, 0x41, 0x73, 0x69, 0x97, 0xcb,
	0x27, 0x9e, 0x43, 0x22, 0x4e, 0xe2, 0x89, 0x5c,
	0xb7, 0x9a, 0xc7, 0xb2, 0xcc, 0x58, 0xd7, 0xe0,
	0x67, 0x5d, 0x89, 0xcb, 0xe7, 0x5d, 0x50, 0x66,
	0x82, 0x82, 0x3b, 0xd6, 0xdd, 0xb3, 0x27, 0xd5,
	0xd9, 0x15, 0x34, 0x54, 0xb0, 0xd2, 0x75, 0x64,
	0x42, 0x1a, 0xec, 0x56, 0xa9, 0x68, 0xb5, 0x21,
	0x13, 0x07, 0x81, 0x05, 0xd1, 0xd4, 0x46, 0x6e,
	0xab, 0x45, 0x35, 0x1b, 0x77, 0xaa, 0xed, 0x7f,
	0xea, 0xb3, 0xee, 0x68, 0xad, 0x33, 0x50, 0xde,
	0xb3, 0x23, 0xb5, 0x4e, 0xcb, 0xea, 0x7c, 0xe8,
	0x71, 0xdc, 0x37, 0x45, 0xea, 0x00, 0x5f, 0x4d,
	0x90, 0x16, 0x47, 0x58, 0x6a, 0xd8, 0x4f, 0x93,
	0xff, 0x81, 0x5a, 0xa6, 0x6c, 0x8c, 0x82, 0x93,
	0xb5, 0xbe, 0x0a, 0xe1, 0x59, 0x66, 0x93, 0xfb,
	0x29, 0xe4, 0x93, 0xd3, 0x59, 0x68, 0x04, 0xca,
	0xd8, 0xfc, 0x59, 0xd4, 0xdd, 0xc5, 0xb6, 0xd7,
	0xc3, 0x85, 0x60, 0x55, 0x16, 0x65, 0x73, 0x4b,
	0xee, 0xf2, 0xd3, 0x59, 0x7b, 0x65, 0x64, 0x22,
	0xe2, 0x27, 0x7e, 0xf6, 0x47, 0x94, 0x9b, 0xaf,
	0x2b, 0x00, 0x53, 0xd8, 0xf9, 0xf7, 0x8b, 0x15,
	0xdb, 0xc9, 0xe9, 0xbe, 0xd2, 0x46, 0x8b, 0xce,
	0x06, 0xc7, 0xf8, 0xfc, 0x5b, 0x6e, 0x56, 0x27,
	0x44, 0xae, 0xde, 0xf7, 0xdc, 0x0d, 0x8e, 0xc2,
	0x33, 0x28, 0x1d, 0xac, 0xe5, 0xf8, 0x34, 0x13,
	0xf2, 0x55, 0xdb, 0x2a, 0xc9, 0xb8, 0x32, 0xe3,
	0xa6, 0x45, 0x61, 0x13, 0x1e, 0x09, 0xd1, 0xd1,
	0xf9, 0x80, 0x9d, 0x1e, 0x3f, 0x5a, 0x43, 0xcc,
	0x95, 0x7e, 0xa0, 0x98, 0xca, 0x50, 0x1b, 0x9a,
	0xae, 0x2f, 0x20, 0xdf, 0x23, 0x42, 0xd0, 0x54,
	0x76, 0x75, 0xf6, 0xe5, 0xef, 0xbe, 0x3d, 0xe7,
	0xa6, 0xa5, 0xa1, 0xb3, 0x99, 0x03, 0x24, 0x94,
	0xfc, 0x0a, 0xc2, 0xe4, 0xd0, 0x85, 0xa6, 0x71,
	0xb7, 0x61, 0x9e, 0x26, 0x07, 0x6d, 0xcd, 0xe7,
	0x1d, 0x5e, 0xa0, 0xbc, 0xf4, 0x16, 0x03, 0x32,
	0xf6, 0x26, 0xd4, 0xfe, 0x11, 0x91, 0x97, 0xe4,
	0x0e, 0xd3, 0x6c, 0xd7, 0x1e, 0x21, 0x3f, 0x62,
	0xb6, 0xf3, 0x3f, 0x46, 0x9d, 0xc0, 0x91, 0x65,
	0x44, 0x08, 0x45, 0xde, 0x55, 0x98, 0x89, 0x7a,
	0x8e, 0x0a, 0x1c, 0x47, 0xd0, 0x8b, 0x06, 0x82,
	0x73, 0xe1, 0x87, 0xba, 0xdd, 0xac, 0x4d, 0x33,


};

static const char tuning_blk_8b[TUNING_LEN*512] = {
	/*hs200/uhs*/
	0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
	0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
	0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
	0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
	0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
	0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
	0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
	0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
	0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
	0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
	0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
	0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
	0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
	0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
	0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,

	0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
	0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
	0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
	0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
	0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
	0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
	0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
	0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
	0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
	0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
	0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
	0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
	0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
	0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
	0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,

	0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
	0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
	0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
	0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
	0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
	0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
	0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
	0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
	0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
	0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
	0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
	0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
	0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
	0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
	0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,

	0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
	0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
	0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
	0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
	0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
	0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
	0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
	0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
	0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
	0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
	0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
	0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
	0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
	0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
	0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,

	/*0xf*/
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,

	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,

	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,

	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
	0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,

	/*0x1e*/
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,

	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,

	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,

	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,
	0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE,

	/*0x5a*/
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,

	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,

	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,

	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
	0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,

	/*wifi*/
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,
  	0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x18,
  	0xc5, 0x00, 0x10, 0x18, 0x01, 0x12, 0xf8, 0x4b,
  	0x11, 0x42, 0x00, 0x19, 0x03, 0x01, 0x00, 0x00,
  	0x05, 0x10, 0x00, 0x18, 0xc5, 0x10, 0x10, 0x18,
  	0x30, 0x43, 0x04, 0x16, 0x00, 0x90, 0x10, 0x18,
  	0x01, 0x00, 0xf8, 0x4b, 0x11, 0x42, 0x00, 0x27,

	/*0xf1*/
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,

	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,

	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,

	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,

	/*0xd2(change form 0xe1/0x1e)*/
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,

	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,

	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,

	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,
	0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02, 0xfd, 0x02,

	/*0xb4(change form 0xe1/0x1e)*/
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,

	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,

	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,

	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,
	0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04, 0xfb, 0x04,


	/*0x78(change form 0xe1/0x1e)*/
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,

	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,

	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,

	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,
	0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80,

	/*rand*/
	0xe4, 0x4f, 0x76, 0xbb, 0xf0, 0xb7, 0xe0, 0xdb,
	0xb9, 0x1f, 0x9f, 0xfb, 0x7e, 0x9b, 0x03, 0x7d,
	0x2e, 0x32, 0x8f, 0x29, 0x7a, 0x9b, 0xab, 0x16,
	0x2f, 0x44, 0x99, 0xce, 0xc3, 0x99, 0xaa, 0xad,
	0x2d, 0x82, 0xb2, 0x8a, 0xfa, 0x2d, 0xb9, 0x9a,
	0x9e, 0x0f, 0xf3, 0x90, 0x08, 0x25, 0xf3, 0x09,
	0x79, 0x80, 0x1b, 0x28, 0x95, 0x00, 0x57, 0x7d,
	0xbb, 0x60, 0x0b, 0x2c, 0x92, 0x72, 0x49, 0x4b,
	0xe4, 0xac, 0x48, 0x8b, 0xb0, 0xe4, 0x11, 0x1b,
	0x7a, 0x58, 0x7c, 0xc9, 0xe6, 0xf1, 0x5b, 0x6b,
	0x85, 0xc9, 0xf5, 0x7d, 0xef, 0xea, 0xb6, 0x0b,
	0x12, 0x59, 0x24, 0xd2, 0xc9, 0x53, 0x15, 0xa2,
	0xb1, 0xd6, 0x1f, 0x06, 0x38, 0x63, 0x51, 0x27,
	0xf6, 0x03, 0x20, 0xee, 0x41, 0x88, 0xa4, 0x69,
	0xfb, 0x15, 0x05, 0x70, 0xaf, 0xe0, 0x30, 0x88,
	0xdc, 0x37, 0xce, 0x07, 0x91, 0xc1, 0x76, 0x79,
	0x3a, 0x07, 0x21, 0x43, 0xba, 0x32, 0xdf, 0x86,
	0xba, 0x16, 0xc9, 0x46, 0x40, 0x70, 0x37, 0xcc,
	0x83, 0x6c, 0x33, 0x48, 0xfe, 0x6b, 0x2d, 0xbb,
	0xc3, 0x02, 0xf0, 0x14, 0x12, 0x46, 0xd4, 0x99,
	0x2a, 0x47, 0x35, 0x89, 0x5f, 0xda, 0x25, 0x00,
	0x6d, 0x9c, 0x5e, 0x1a, 0x0c, 0x33, 0x7a, 0x5b,
	0xc4, 0xd7, 0x67, 0x4f, 0x03, 0x12, 0x15, 0x6d,
	0x6d, 0xc3, 0x71, 0x41, 0x73, 0x69, 0x97, 0xcb,
	0x27, 0x9e, 0x43, 0x22, 0x4e, 0xe2, 0x89, 0x5c,
	0xb7, 0x9a, 0xc7, 0xb2, 0xcc, 0x58, 0xd7, 0xe0,
	0x67, 0x5d, 0x89, 0xcb, 0xe7, 0x5d, 0x50, 0x66,
	0x82, 0x82, 0x3b, 0xd6, 0xdd, 0xb3, 0x27, 0xd5,
	0xd9, 0x15, 0x34, 0x54, 0xb0, 0xd2, 0x75, 0x64,
	0x42, 0x1a, 0xec, 0x56, 0xa9, 0x68, 0xb5, 0x21,
	0x13, 0x07, 0x81, 0x05, 0xd1, 0xd4, 0x46, 0x6e,
	0xab, 0x45, 0x35, 0x1b, 0x77, 0xaa, 0xed, 0x7f,
	0xea, 0xb3, 0xee, 0x68, 0xad, 0x33, 0x50, 0xde,
	0xb3, 0x23, 0xb5, 0x4e, 0xcb, 0xea, 0x7c, 0xe8,
	0x71, 0xdc, 0x37, 0x45, 0xea, 0x00, 0x5f, 0x4d,
	0x90, 0x16, 0x47, 0x58, 0x6a, 0xd8, 0x4f, 0x93,
	0xff, 0x81, 0x5a, 0xa6, 0x6c, 0x8c, 0x82, 0x93,
	0xb5, 0xbe, 0x0a, 0xe1, 0x59, 0x66, 0x93, 0xfb,
	0x29, 0xe4, 0x93, 0xd3, 0x59, 0x68, 0x04, 0xca,
	0xd8, 0xfc, 0x59, 0xd4, 0xdd, 0xc5, 0xb6, 0xd7,
	0xc3, 0x85, 0x60, 0x55, 0x16, 0x65, 0x73, 0x4b,
	0xee, 0xf2, 0xd3, 0x59, 0x7b, 0x65, 0x64, 0x22,
	0xe2, 0x27, 0x7e, 0xf6, 0x47, 0x94, 0x9b, 0xaf,
	0x2b, 0x00, 0x53, 0xd8, 0xf9, 0xf7, 0x8b, 0x15,
	0xdb, 0xc9, 0xe9, 0xbe, 0xd2, 0x46, 0x8b, 0xce,
	0x06, 0xc7, 0xf8, 0xfc, 0x5b, 0x6e, 0x56, 0x27,
	0x44, 0xae, 0xde, 0xf7, 0xdc, 0x0d, 0x8e, 0xc2,
	0x33, 0x28, 0x1d, 0xac, 0xe5, 0xf8, 0x34, 0x13,
	0xf2, 0x55, 0xdb, 0x2a, 0xc9, 0xb8, 0x32, 0xe3,
	0xa6, 0x45, 0x61, 0x13, 0x1e, 0x09, 0xd1, 0xd1,
	0xf9, 0x80, 0x9d, 0x1e, 0x3f, 0x5a, 0x43, 0xcc,
	0x95, 0x7e, 0xa0, 0x98, 0xca, 0x50, 0x1b, 0x9a,
	0xae, 0x2f, 0x20, 0xdf, 0x23, 0x42, 0xd0, 0x54,
	0x76, 0x75, 0xf6, 0xe5, 0xef, 0xbe, 0x3d, 0xe7,
	0xa6, 0xa5, 0xa1, 0xb3, 0x99, 0x03, 0x24, 0x94,
	0xfc, 0x0a, 0xc2, 0xe4, 0xd0, 0x85, 0xa6, 0x71,
	0xb7, 0x61, 0x9e, 0x26, 0x07, 0x6d, 0xcd, 0xe7,
	0x1d, 0x5e, 0xa0, 0xbc, 0xf4, 0x16, 0x03, 0x32,
	0xf6, 0x26, 0xd4, 0xfe, 0x11, 0x91, 0x97, 0xe4,
	0x0e, 0xd3, 0x6c, 0xd7, 0x1e, 0x21, 0x3f, 0x62,
	0xb6, 0xf3, 0x3f, 0x46, 0x9d, 0xc0, 0x91, 0x65,
	0x44, 0x08, 0x45, 0xde, 0x55, 0x98, 0x89, 0x7a,
	0x8e, 0x0a, 0x1c, 0x47, 0xd0, 0x8b, 0x06, 0x82,
	0x73, 0xe1, 0x87, 0xba, 0xdd, 0xac, 0x4d, 0x33,


};



/*
#define isascii(c)	(((unsigned char)(c))<=0x7f)
#define isprint(c)	((((unsigned char)(c))>=32 && ((unsigned char)(c))<=126) \
			|| (((unsigned char)(c))>=160 && ((unsigned char)(c))<=255))


#define DBG_DUMP_BUF_LEN 	(128)
#define MAX_DUMP_PER_LINE	(16)
#define MAX_DUMP_PER_LINE_HALF	(MAX_DUMP_PER_LINE >> 1)
void hexdump(char *prompt, char *buf, int len)
{
	int i, j;
	int head = 0;

	printf("Dump (%s): len %d\n", prompt, len);
	for (i = 0; i < len;) {
		if (i % MAX_DUMP_PER_LINE == 0) {
			printf("%08x  ", i);
			head = i;
		}
		printf("%02x ", buf[i]&0xff);
		if (i % MAX_DUMP_PER_LINE == MAX_DUMP_PER_LINE_HALF-1)
			printf(" ");
		if (i % MAX_DUMP_PER_LINE == MAX_DUMP_PER_LINE-1
			|| i==len-1) {
			for (j=i-head+1; j<MAX_DUMP_PER_LINE; j++)
				printf("   ");
			printf(" |");
			for (j=head; j<=i; j++) {
				if (isascii(buf[j]) && isprint(buf[j]))
					printf("%c", buf[j]);
				else
					printf(".");
			}
			printf("|\n");
		}

		i++;
	}

	printf("\n");
}



s16 aw_rand(s32 *seed)
{
	s32 RandMax  = 0x7fff;
	s32 tmp;

	tmp = (*seed) * 0x000343FD;
	tmp+= 0x00269EC3;
	*seed = tmp;
	tmp >>= 16;
	tmp &= RandMax;
	return (s16)tmp;
}


void print_rand(void)
{
	int i =0;
	int seed = 0x55aa;
	char rand[512]={0};
	for(i=0;i<512;i++){
		rand[i]=aw_rand(&seed);
	}
	hexdump("rand data", (void*)rand, 512);
}
*/


static int write_tuning_try_freq(struct mmc *mmc,u32 clk)
{
	int ret = 0;
	const char *std_pattern = NULL;
	char *rcv_pattern = malloc(TUNING_LEN*512);
	u32 err_no = 0;
	if(rcv_pattern == NULL){
		return -1;
	}
	if(mmc->bus_width == 4){
		std_pattern = tuning_blk_4b;
	}else if(mmc->bus_width == 8){
		std_pattern = tuning_blk_8b;
	}else if(mmc->bus_width == 1){
		MMCINFO("Not support 1 bit tuning now\n");
		ret = -1;
		goto out;
	}


	do{
		mmc_set_clock(mmc, clk);
		ret = mmc_bwrite(mmc->control_num,
						TUNING_ADD,
						TUNING_LEN,
						std_pattern);
		MMCDBG("Write pattern ret = %d\n",ret);
		if(ret != TUNING_LEN){//failed
			MMCINFO(" write failed\n");
			err_no = mmc->get_detail_errno(mmc);
			//if write failed and block len>1,send stop for next try
			//no care if it is successed
			if(TUNING_LEN>1){
				MMCINFO(" Send stop\n");
				mmc_send_manual_stop(mmc);
			}
		}else{//ok
			MMCINFO(" write ok\n");
			//read pattern and compare with the pattern show sent
			ret = mmc_bread(mmc->control_num,
							TUNING_ADD,
							TUNING_LEN,
							rcv_pattern);
			if(ret != TUNING_LEN){
				MMCINFO(" read failed\n");
				err_no = mmc->get_detail_errno(mmc);
				//if read failedand block len>1,send stop for next try
				//no care if it is successed
				if(TUNING_LEN>1){
					MMCINFO(" Send stop\n");
					mmc_send_manual_stop(mmc);
				}
			}else{
				ret = memcmp(std_pattern, rcv_pattern, TUNING_LEN*512);
				if(ret){
					MMCINFO(" pattern compare fail\n");
					err_no = 0xffffffff;//force retry
				}else{
					MMCINFO(" Pattern compare ok\n");
					MMCINFO(" Write tuning pattern ok\n");
					goto out;
				}
			}
		}
	}while(!mmc->decide_retry(mmc,err_no,0));
	MMCINFO(" Write tuning pattern failded\n");
	ret = -1;

out:
	free(rcv_pattern);
	return ret;

}



static int sunxi_write_tuning(struct mmc *mmc)
{
	u32 freqs[] = { 400000, 25*1000*1000, 50*1000*1000};
	int  i 	= 0;
	int  ret 	= -1;
	int clk_bak = mmc->clock;

	if(mmc->decide_retry==NULL){
		MMCINFO("NO support tuning\n");
		return 0;
	}

	//reset rety count
	mmc->decide_retry(mmc,0,1);
	for(i=0;i<sizeof(freqs)/sizeof(freqs[0]);i++){
		ret = write_tuning_try_freq(mmc,freqs[i]);
		if(!ret){
			//recover the clock before wiite patten
			mmc_set_clock(mmc, clk_bak);
			return ret;
		}
	}
	return ret;
}


static ulong sunxi_read_tuning(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
{
	lbaint_t cur, blocks_todo = blkcnt;

	if (blkcnt == 0){
		MMCINFO("blkcnt should not be 0\n");
		return 0;
	}

	struct mmc *mmc = find_mmc_device(dev_num);
	if (!mmc){
		MMCINFO("Can not find mmc dev\n");
		return 0;
	}

	if ((start + blkcnt) > mmc->block_dev.lba) {
		MMCINFO("MMC: block number 0x%lx exceeds max(0x%lx)\n",
			start + blkcnt, mmc->block_dev.lba);
		return 0;
	}

	if (mmc_set_blocklen(mmc, mmc->read_bl_len)){
		MMCINFO("Set block len failed\n");
		return 0;
	}

	do {
		cur =1;//force to read 1 block a time
		if(mmc_read_blocks(mmc, dst, start, cur) != cur){
			MMCINFO("block read failed\n");
			return 0;
		}
		blocks_todo -= cur;
		start += cur;
		dst = (char*)dst + cur * mmc->read_bl_len;
	} while (blocks_todo > 0);

	return blkcnt;
}




static int sunxi_get_sdly_win(struct mmc *mmc,int start_in,
					int end_in,int *start_out,
					int *end_out,s8 *sdly,
					const char *std_pat,
					int repeat_times)
{
		int i 				= 0;
		int  j				= 0;
		int ret 			= 0;
		char *rcv_pat 	= malloc(TUNING_LEN*512);

		if(rcv_pat == NULL){
			MMCINFO(" malloc mem failed\n");
			ret = -1;
			return ret;
		}

		if((start_in>end_in)
			||(start_out==NULL)
			||(end_out==NULL)
			||(std_pat==NULL)){
			MMCINFO("Input parameter error\n");
			ret = -1;
			goto out;
		}

		/*
		tick_printf("[mmc]:*************************Try delay win[");
		for(i=start_in;i<=end_in;i++){
			printf("%d",sdly[i]);
		}
		printf("]*************************\n");
		*/


		/**********find start point************/
		for(i=start_in;i<=end_in;i++){
			//read pattern and compare with the pattern show sent
			mmc->update_sdly(mmc,sdly[i]);//update sdly
			mmc_set_clock(mmc, mmc->clock);//make sdly efficiency
			for(j=0;j<repeat_times;j++){
				ret = sunxi_read_tuning(mmc->control_num,
								TUNING_ADD,
								TUNING_LEN,
								rcv_pat);
				if(ret != TUNING_LEN){
					MMCINFO(" read failed\n");
					//if read failedand block len>1,send stop for next try
					//no care if it is successed
					//if(TUNING_LEN>1){
					//	MMCINFO(" Send stop\n");
					//	mmc_send_manual_stop(mmc);
					//}
					break;
				}
				ret = memcmp(std_pat, rcv_pat, TUNING_LEN*512);
				if(ret){
					MMCINFO(" pattern compare fail\n");
					break;
				}

				MMCDBG(" Pattern compare ok in sample ponit %d\n",sdly[i]);
			}
			if(j>=repeat_times){
				break;
			}
		}

		if(i>end_in){
			//MMCINFO("Can not find sample point between %d-%d\n",sdly[start_in],sdly[end_in]);
			tick_printf("[mmc]:Can not find sample point between [");
			for(i=start_in;i<=end_in;i++){
				printf("%d",sdly[i]);
			}
			printf("]\n");
			ret = -1;
			goto out;
		}
		*start_out = i;

		/**********find end point************/
		for(i++;i<=end_in;i++){
			//read pattern and compare with the pattern show sent
			mmc->update_sdly(mmc,sdly[i]);//update sdly
			mmc_set_clock(mmc, mmc->clock);//make sdly efficiency
			for(j=0;j<repeat_times;j++){
				ret = sunxi_read_tuning(mmc->control_num,
								TUNING_ADD,
								TUNING_LEN,
								rcv_pat);
				if(ret != TUNING_LEN){
					MMCINFO(" read failed\n");
					//if read failedand block len>1,send stop for next try
					//no care if it is successed
					//if(TUNING_LEN>1){
					//	MMCINFO(" Send stop\n");
					//	mmc_send_manual_stop(mmc);
					//}
					break;
				}

				ret = memcmp(std_pat, rcv_pat, TUNING_LEN*512);
				if(ret){
					MMCINFO(" pattern compare fail\n");
					break;
				}
				MMCDBG(" Pattern compare ok in sample ponit %d\n",sdly[i]);
			}
			if(j<repeat_times){
				break;
			}

		}

		if(i>end_in){
			 *end_out = end_in;
		}else{
			*end_out = i-1;
		}

		tick_printf("[mmc]:*************************delay win[");
		for(i=*start_out;i<=*end_out;i++){
			printf("%d",sdly[i]);
		}
		printf("]*************************\n");
		ret = 0;

out:
		free(rcv_pat);
		return ret;

}



static void calc_real_dly(u32 pll_clk,u32 clk,s8 *real_delay)
{
	int i 					= 0;
	char sple_dly_real[8]	={1,2,3,4,5,6,7,0};
	u32 delay0 			= 0;
	char sple_win_str[9]	= {0};

	/**********calc readlly delay 0**************/
	/*calc really delay 0*/

	delay0 = pll_clk/clk/2;
	MMCDBG("delay0: %d, sclk %d,card clk %d\n",delay0,pll_clk,clk);
	for(i=0;i<7;i++){
		if(delay0<= sple_dly_real[i]){
			break;
		}
	}

	if(i<7){
		memmove(sple_dly_real+i+1,sple_dly_real+i,7-i);
		sple_dly_real[i] = 0;
	}

	for(i = 0;i<=7;i++){
		sprintf(sple_win_str+i,"%d",sple_dly_real[i]);
	}
	MMCINFO("real sample win [%s]\n",sple_win_str);
	memcpy(real_delay,sple_dly_real,8);
	/**********calc readlly delay 0 end**************/
}



static int sunxi_exe_tuning(struct mmc *mmc)
{
	int ret 				= 0;
	int i 					= 0;
	const char *std_pat 	= NULL;
	s8 sple_dly_real[8]	={1,2,3,4,5,6,7,0};

	s32 sple_start0 		= 0;
	s32 sple_end0 		= 0;
	u32 win0				= 0;

	s32 sple_start1 		= 0;
	s32 sple_end1 		= 0;
	u32 win1				= 0;
	//u32 f_max_bak		= 0;


	u32 tuning_freqs[]		= {52*1000*1000,26*1000*1000};
	s32 tuning_times	= 0;
	int suit_sdly = 0;

	//decide tuning freq and times
	if (IS_SD(mmc)) {
		if (mmc->card_caps & MMC_MODE_HS){
			tuning_freqs[1]= 25000000;
			tuning_freqs[0]= 50000000;
			tuning_times = 2;
		}else{
			tuning_freqs[0]= 25000000;
			tuning_times = 1;
		}
	} else {
		if (mmc->card_caps & MMC_MODE_HS) {
			if (mmc->card_caps & MMC_MODE_HS_52MHz){
				tuning_freqs[1]= 26000000;
				tuning_freqs[0]= 52000000;
				tuning_times = 2;
			}else{
				tuning_freqs[0]= 26000000;
				tuning_times = 1;
			}
		} else{
			tuning_freqs[0]= 20000000;
			tuning_times = 1;
		}
	}

	if(mmc->update_sdly==NULL){
		MMCINFO("update_sdly not implement\n");
		return -1;
	}



	if(mmc->bus_width == 4){
		std_pat = tuning_blk_4b;
	}else if(mmc->bus_width == 8){
		std_pat = tuning_blk_8b;
	}else if(mmc->bus_width == 1){
		MMCINFO("Not support 1 bit tuning now\n");
		ret = -1;
		goto out;
	}

	//f_max_bak = mmc->f_max;
	//mmc->f_max = 100*1000*1000;

	//for(i=0;i<sizeof(tuning_freqs)/sizeof(tuning_freqs[0]);i++){
	for(i=0;i<tuning_times;i++){
		MMCDBG("**************************Start tuning in freq %d**************************\n",tuning_freqs[i]);
		mmc_set_clock(mmc, tuning_freqs[i]);
		calc_real_dly(mmc->pll_clock,mmc->clock,sple_dly_real);
		ret = sunxi_get_sdly_win(mmc,0,7,&sple_start0,&sple_end0,sple_dly_real,std_pat,REPEAT_TIMES);
		if(ret){
			MMCDBG("Can not find sample point in win0\n");
			MMCINFO("**************Failed to find sample point in freq %d(%d)**************\n",tuning_freqs[i],mmc->clock);
			win0 = 0;
			//continue;
			//if we can not find sample point, we assume that there is something wrong not related to sample point
			ret = -1;
			goto out;
		}else{
			MMCDBG("find sample point in win0\n");
			if(sple_end0==sple_start0){
				win0 = 1;
			}else{
				win0 = sple_end0-sple_start0+1;
			}
		}

		ret = sunxi_get_sdly_win(mmc,sple_end0+2,7,&sple_start1,&sple_end1,sple_dly_real,std_pat,REPEAT_TIMES);
		if(ret){
			MMCDBG("Can not find sample point in win1\n");
			win1 =0;
		}else{
			MMCDBG("find sample point in win1\n");
			if(sple_end1==sple_start1){
				win1 = 1;
			}else{
				win1 = sple_end1-sple_start1+1;
			}
		}

		if(win0>win1){
			suit_sdly = sple_start0+(win0)/2;
		}else{
			suit_sdly = sple_start1+(win1)/2;
		}

		MMCINFO("!!!!!!!!!!!!Find suitable sample point %d in freq %d(%d)!!!!!!!!!!!!\n",sple_dly_real[suit_sdly],tuning_freqs[i],mmc->clock);

		if(tuning_freqs[i]<=26000000){
			mmc->sdly_tuning.sdly_25M = sple_dly_real[suit_sdly];
		}else if(tuning_freqs[i]<=52000000){
			mmc->sdly_tuning.sdly_50M = sple_dly_real[suit_sdly];
		}else{
			MMCINFO("The freq is over 52M,not be dealt with now\n");
			ret = -1;
			goto out;
		}

		mmc->update_sdly(mmc,sple_dly_real[suit_sdly]);//update sdly
	}

//	mmc->f_max = f_max_bak;
//	mmc_set_clock(mmc, mmc->clock_after_init);//recover clock when init ok
	//set clock for burn fireware
	mmc_set_clock(mmc, tuning_freqs[0]);
	MMCINFO("---------------mmc clock %d-----------\n", mmc->clock);
	ret = 0;
out:
	return ret;
}







int mmc_write_info(int dev_num,void *buffer,u32 buffer_size)
{
	struct mmc *mmc = find_mmc_device(dev_num);
	int work_mode = uboot_spare_head.boot_data.work_mode;
	if(mmc==NULL){
		MMCINFO("Can not find mmc\n");
		return -1;
	}

	if(mmc->sample_mode ==AUTO_SAMPLE_MODE
		&& work_mode!= WORK_MODE_BOOT){

		if(sizeof(struct tuning_sdly)>buffer_size){
			MMCINFO("size of tuning_sdly over %d\n",buffer_size);
			return -1;
		}

		memcpy(buffer,(void *)&mmc->sdly_tuning,sizeof(sizeof(struct tuning_sdly)));
		MMCINFO("write mmc info ok\n");
		return 0;
	}
	return -1;

}



static int mmc_init_product(struct mmc *mmc)
{
	int err;

	//while((*(volatile unsigned int *)0) != 1);
	if (mmc->has_init){
		MMCINFO("Has init\n");
		return 0;
	}

retry:

	err = mmc->init(mmc);

	if (err){
		MMCINFO("mmc->init error\n");
		return err;
	}
	mmc_set_bus_width(mmc, 1);
	mmc_set_clock(mmc, 1);

	/* Reset the Card */
	err = mmc_go_idle(mmc);

	if (err){
		MMCINFO("mmc go idle error\n");
		return err;
	}
	/* The internal partition reset to user partition(0) at every CMD0*/
	mmc->part_num = 0;

	MMCINFO("************Try SD card %d************\n",mmc->control_num);
	/* Test for SD version 2 */
	err = mmc_send_if_cond(mmc);
	if(err && !sunxi_need_rty(mmc)){
		goto retry;
	}

    /* Now try to get the SD card's operating condition */
	err = sd_send_op_cond(mmc);
	if(err && !sunxi_need_rty(mmc)){
		goto retry;
	}

	/* If the command timed out, we check for an MMC card */
	if (err == -1){
		if(!sunxi_need_rty(mmc)){
			goto retry;
		}
		MMCINFO("*Try MMC card %d*\n",mmc->control_num);
		err = mmc_send_op_cond(mmc);
		if(err && !sunxi_need_rty(mmc)){
			goto retry;
		}

		if (err) {
			MMCINFO("Card did not respond to voltage select!\n");
			MMCINFO("*SD/MMC %d init error!*\n",mmc->control_num);
			return UNUSABLE_ERR;
		}
	}

	err = mmc_startup(mmc);
	if (err){
		MMCINFO("*SD/MMC %d init error!*\n",mmc->control_num);
		mmc->has_init = 0;
	}
	else{
		mmc->has_init = 1;
		//MMCINFO("************SD/MMC %d init OK!!!************\n",mmc->control_num);
	}

	if(err && !sunxi_need_rty(mmc)){
		goto retry;
	}


	err = sunxi_write_tuning(mmc);
	if(err){
		MMCINFO("Write pattern failed\n");
		return err;
	}

	err = sunxi_exe_tuning(mmc);
	if(err){
		return err;
	}


	init_part(&mmc->block_dev);

	return err;

}


static int mmc_init_boot(struct mmc *mmc)
{
	int err;
	int work_mode = uboot_spare_head.boot_data.work_mode;

	if (mmc->has_init){
		MMCINFO("Has init\n");
		return 0;
	}

	err = mmc->init(mmc);

	if (err){
		MMCINFO("mmc->init error\n");
		return err;
	}
	mmc_set_bus_width(mmc, 1);
	mmc_set_clock(mmc, 1);

	/* Reset the Card */
	err = mmc_go_idle(mmc);

	if (err){
		MMCINFO("mmc go idle error\n");
		return err;
	}
	/* The internal partition reset to user partition(0) at every CMD0*/
	mmc->part_num = 0;

	MMCINFO("*Try SD card %d*\n",mmc->control_num);
	/* Test for SD version 2 */
	err = mmc_send_if_cond(mmc);

    /* Now try to get the SD card's operating condition */
	err = sd_send_op_cond(mmc);

	/* If the command timed out, we check for an MMC card */
	if (err == -1){
		MMCINFO("*Try MMC card %d*\n",mmc->control_num);
		err = mmc_send_op_cond(mmc);
		if (err) {
			MMCINFO("Card did not respond to voltage select!\n");
			MMCINFO("***SD/MMC %d init error!!!***\n",mmc->control_num);
			return UNUSABLE_ERR;
		}
	}

	err = mmc_startup(mmc);
	if (err){
		MMCINFO("*SD/MMC %d init error!!*\n",mmc->control_num);
		mmc->has_init = 0;
	}
	else{
		mmc->has_init = 1;
		//MMCINFO("************SD/MMC %d init OK!!!************\n",mmc->control_num);
	}


	if((mmc->sample_mode == AUTO_SAMPLE_MODE)
		&&(work_mode == WORK_MODE_BOOT)){
		u32 suit_sdly = 0;
		struct tuning_sdly  *sdly= (struct tuning_sdly  *)uboot_spare_head.boot_data.sdcard_spare_data;

		//MMCINFO("****************sdly:%d*************************\n",sdly->sdly_50M);
		suit_sdly = sdly->sdly_50M;
		if(script_parser_patch("mmc2_para","sdc_sdly_50M",&suit_sdly,1) == SCRIPT_PARSER_OK){
			int rval = 0;
			script_parser_fetch("mmc2_para","sdc_sdly_50M", &rval, 1);
			MMCINFO("set kernel %s %d ok\n","sdc_sdly_50M",rval);
		}else{
			MMCINFO("set kernel %s failed\n","sdc_sdly_50M");
		}

		suit_sdly = sdly->sdly_25M;
		if(script_parser_patch("mmc2_para","sdc_sdly_25M",&suit_sdly,1) == SCRIPT_PARSER_OK){
			int rval = 0;
			script_parser_fetch("mmc2_para","sdc_sdly_25M", &rval, 1);
			MMCINFO("set kernel %s %d ok\n","sdc_sdly_25M",rval);
		}else{
			MMCINFO("set kernel %s failed\n","sdc_sdly_25M");
		}

	}
	init_part(&mmc->block_dev);
	return err;
}

int mmc_init(struct mmc *mmc)
{
	int work_mode = uboot_spare_head.boot_data.work_mode;
	int ret = 0;

#if defined(CONFIG_ARCH_SUN9IW1P1)
	if(gd->securemode == SUNXI_SECURE_MODE_NO_SECUREOS)
    {
		mmc->block_dev.lun = 0x0;
		mmc->block_dev.type = 0x0;
		mmc->block_dev.blksz = 0x200;
		//use max lba/capacity becauese we can not get capacity from sd,because we can not get rca.
		//for eMMC,we can get capacity,but for compatible to sd,we use max too
		mmc->block_dev.lba = 0xffffffff;
		mmc->capacity = 0xffffffff;
		//mmc->block_dev.part_type = 0x2;
		//assume high capacity for we do not init card here
		mmc->high_capacity = 1;
		//mmc->b_max = (0x20<<4);//(0x10000>>5);
		//mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
		mmc->read_bl_len = 0x200;
		mmc->write_bl_len = 0x200;
		//mmc->erase_grp_size = 0x1;
		mmc->part_config = MMCPART_NOAVAILABLE;
		mmc->has_init = 1;

		return 0;
	}
#endif

	//while((*(volatile unsigned int *)0) != 1);
	if((mmc->sample_mode == AUTO_SAMPLE_MODE)
		&&(work_mode != WORK_MODE_BOOT)){
		return mmc_init_product(mmc);
	}
	ret = mmc_init_boot(mmc);

	if (mmc->drv_wipe_feature & DRV_PARA_DISABLE_EMMC_SANITIZE)
		mmc->secure_feature &= (~EXT_CSD_SEC_SANITIZE);
	else if (mmc->drv_wipe_feature & DRV_PARA_DISABLE_EMMC_SECURE_PURGE)
		mmc->secure_feature &= (~EXT_CSD_SEC_ER_EN);
	else if (mmc->drv_wipe_feature & DRV_PARA_DISABLE_EMMC_TRIM)
		mmc->secure_feature &= (~EXT_CSD_SEC_GB_CL_EN);

	//MMCINFO("========================================\n");
	//MMCINFO("mmc->block_dev.lba:      %d Sectors\n", mmc->block_dev.lba);
	//MMCINFO("wr_blk_len:              0x%x Byte\n", mmc->write_bl_len);
	MMCINFO("erase_grp_size:0x%xWrBlk * 0x%x = 0x%x Byte\n",
			mmc->erase_grp_size, mmc->write_bl_len, mmc->erase_grp_size*mmc->write_bl_len);
	//MMCINFO("erase_to:                %d ms\n", mmc->erase_timeout);
	//MMCINFO("trim_discard_to:         %d ms\n", mmc->trim_discard_timeout);
	//MMCINFO("secure_tirm_to:          %d ms\n", mmc->secure_erase_timeout);
	//MMCINFO("secure_erase_to:         %d ms\n", mmc->secure_trim_timeout);
	
    
    MMCDBG("support sanitze:         %d \n", mmc->secure_feature & EXT_CSD_SEC_SANITIZE);
	MMCDBG("support trim:            %d \n", mmc->secure_feature & EXT_CSD_SEC_GB_CL_EN);
	MMCDBG("support secure purge op: %d \n", mmc->secure_feature & EXT_CSD_SEC_ER_EN);
	MMCDBG("secure removal type:     0x%x\n", mmc->secure_removal_type);
	
    MMCINFO("secure_feature 0x%x\n", mmc->secure_feature);
    MMCINFO("secure_removal_type  0x%x\n", mmc->secure_removal_type);

    //MMCINFO("========================================\n\n");

	return ret;
}



/*
 * CPU and board-specific MMC initializations.  Aliased function
 * signals caller to move on
 */
static int __def_mmc_init(bd_t *bis)
{
	return -1;
}

int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));

void print_mmc_devices(char separator)
{
	struct mmc *m;
	struct list_head *entry;

	list_for_each(entry, &mmc_devices) {
		m = list_entry(entry, struct mmc, link);

		MMCINFO("%s: %d", m->name, m->block_dev.dev);

		if (entry->next != &mmc_devices)
			printf("%c ", separator);
	}

	printf("\n");
}

int get_mmc_num(void)
{
	//return cur_dev_num;
    return board_mmc_get_num();
}

int mmc_initialize(bd_t *bis)
{
//	INIT_LIST_HEAD (&mmc_devices);

	if (board_mmc_init(bis) < 0)
		cpu_mmc_init(bis);

	print_mmc_devices(',');

	return 0;
}

int mmc_exit(void)
{
	int err;
	int sdc_no = 2;
	struct mmc *mmc = find_mmc_device(sdc_no);
	if(mmc == NULL){
		MMCINFO(" mmc %s not find,so not exit\n",sdc_no);
		return -1;
	}

	MMCINFO("mmc exit start\n");

#if defined(CONFIG_ARCH_SUN9IW1P1)
	if(gd->securemode == SUNXI_SECURE_MODE_NO_SECUREOS)
	{
		MMCINFO("mmc not exit\n");
		return 0;
	}
#endif

	err = mmc->init(mmc);

	if (err){
		MMCINFO("mmc->init error\n");
		MMCINFO("mmc %d exit failed\n",mmc->control_num);
		return err;
	}
	mmc_set_bus_width(mmc, 1);
	mmc_set_clock(mmc, 1);

	/* Reset the Card */
	err = mmc_go_idle(mmc);

	if (err){
		MMCINFO("mmc go idle error\n");
		MMCINFO("mmc %d exit failed\n",mmc->control_num);
		return err;
	}
	/* The internal partition reset to user partition(0) at every CMD0*/
	mmc->part_num = 0;

	//MMCINFO("************Try SD card %d************\n",mmc->control_num);
	/* Test for SD version 2 */
	err = mmc_send_if_cond(mmc);

    /* Now try to get the SD card's operating condition */
	err = sd_send_op_cond(mmc);

	/* If the command timed out, we check for an MMC card */
	if (err == -1){
		//MMCINFO("************Try MMC card %d************\n",mmc->control_num);
		err = mmc_send_op_cond(mmc);

		if (err) {
			MMCINFO("Card did not respond to voltage select!\n");
			MMCINFO("mmc %d exit failed\n",mmc->control_num);
			return UNUSABLE_ERR;
		}
	}

/*
	err = mmc_startup(mmc);
	if (err){
		MMCINFO("************SD/MMC %d init error!!!************\n",mmc->control_num);
		mmc->has_init = 0;
	}
	else{
		mmc->has_init = 1;
		//MMCINFO("************SD/MMC %d init OK!!!************\n",mmc->control_num);
	}
*/

	sunxi_mmc_exit(sdc_no);
	
	MMCINFO("mmc %d exit ok\n",mmc->control_num);
	return err;
}
